' !+JJJJ C\BD#,)=JJJ)AFAD r r х'+lB / X+L DD) +P `   ; A G :ž y! 4 5~yµ5 6y ’ ͒: ! OͻMD2 > BDOS ERR: $Seleh@(LH9LHH/Hh/ H-З( ܈(& ˆ$8 H` *HVDP (ED Z $0x8x D- ܈DD#>J>J>VU)?`8'x0|&HhHh VY)'&Y)xꪽ)' `Hh`V0^*^*>&` aI꽌ɪVɭ1  ͍ %͍͍ʢ͏͕!~# 4͕ ͍:g:s:_g:s!]~$o#~B̩1ɷW|g ͏͕%z͍͍ ͍vCPM3 SYS CPMLDR error: failed to open CPM3.SYS $ CPML!"*(+3111, ).*/ ./3 7??4##+#,,$$ 02<=-.,80^݌Hh Ì Ì݌ Ռ Ռ ՌA ČD Č? ČAEDE?HJ>h Ԍ Ռ Ռ Ռ`HJ>݌h Hh݌`  +JJJJDxǭLp . . T LeϠЯ͠ĠΠ͠ ALCDž=E<= BϠ  =B CL  =B =EAL>? >>?` =2x>!sGx!c8>Gͦ͞0 xGx(Gͦ͞0 xGx@Gͦx2:x22!x!px2 x>2!x>2"x>2#x.%.~ .~8 |&`ƀo66y .>H.yx (`(8` (24?949:4<  %%&&'''))*++++,,----...////23334556667777999:::;;;;<<====>>>????+8<(#!*?#>#0#0 >+/!#9!#:!.#&  &&'(((())***,,.000011112223444556 88889 : << >FG8`0($ p,&"_z]` L/慍ꅺL  !"#$%&'()*+,-./0123456789:;<=>?ct$Perm.$ v{_zW{_zW )8# ? w#JJ |^#V###" ##" ######" !  I* ! I* |! 6ʕ67 * w#w* w#w#w! ^#V#Fͪ' O* &! s#r#p* N#F* ^#V#F* : O}|y* %\8_* DMe - /:w9#/:w92\\B5:9 A/. ~9\ -9/!"5:}28>27>*ͥ.:x9Z^/. \": -f/.en* -v/:x9ʌ/:x92\\B5!"5:}2R>ͽ"d:`:d:͞8(0͹/H02DMv0 q*!Q>6h!Q>/:Q>=O! *d:Nq*:Q><2Q>/:R><2R>   y2 : xo&: W>O&E: N/* " y2 ʹ͗ͻͫʛ* X: O~Jyʔx ʍ ʂJÍNJ# h2 G>G:~X*  IOw!x>Fwx2 2 ~: : 6: w2 i - ` ` ` ` ` ` Ø ü ö ` ó ` ` ` Ô Ì b Í Ì Î Ì Ì Ó Í Ì Ì Ì Ì Ì :x*f +20282!_ "1""9- !y2) !f 0 ^#V" !`i`i"y2, `i"* > !r[2 x:* 2x:, 2x:x2x2x* +~p2+* .}|y#* %* DM"  * s#r* s#r#pyoxgkDM* 0 MD" ! * MD$ : O&! N:  yG>O: ʐÇ* ͒ : ʨn` ~#for2 O͚" }: O* 7" 2 " : O: G2 ! w*  * !~O !>w:ͨ2 4O.5Ϳ: ! S: ͮ: ͛ͳ: < =! wW* M_S -* MD:" : 2 ɯ2 >G=O* ~~w#~2 ~wc~~p2 !" >2 * ~=2 ~2 ͛o>* wx~2x !|2Ep}2Gp!psx: x7! "_>222028!_ "1"9! ":X 2ɯ!f ɉ a M /  ~2 ~2 : 2 : w: w |g}o' )4: O!3yoxg: O&}* : o$~w{ozg ^#V: ʏ> Û͡" ͳ* ç* r" ! ~#l [ I6: <!=6 * J " * K : G/O*  * =d ## I!" 2 =2 !" Û͛o͢͢' ͫ~<7 w@ͩ7: " Û: ~ : 2 : ~ * 6: p w#: w: w*@* }D> $* * T : _2 {20 q* q*0 q*̈́d:8+s#râ/ q* q*ͥ.!S>q> !S>O0:S>0Oq*Z0:S> AOq*!T>q:T>O60:T>O60!V>p+q*U>|O[0*U>}O[0*9>!=8"W>*W>!=8!Y>s:h0:Y>2h\͕60\>645*W>!=8!|s2*9͗8"9>. \~9 -0:9 1 h%"p86y5.50D1U LINK 1.31 $01/04/83?MEMRY$MEMRYX}CPMLDR COMbhMEMORY OVERFLOW, USE [A] SWITCH$INSUFFICIENT MEMORY$OVERLAPPING SEGMENTS$*[> 8+*[>##q#p*[>*[> N#F^#V?8*[> s#r *[> N#F`i"h>*[> N#F `i"j>*h>"f>j>f>͞8ڐ3*f>+*[> ^#V\8DM2_2*f>"f>\3*[> ^#V*j>\8DM2*[>  *[> ͞8Ҿ31*[> N#F*[> *[> N#F͏5!n>s+p+q*[>l>͠84 *[> ~.m9g97;   }INDEX ERROR$MULTIPLE DEFINITION: $MAIN MODULE ERROR$FIRST COMMON NOT LARGEST$COMMON ERR9ͫ8"|>##*|> ~!7!>6D7*>|?7!>66"|>D7!>6:>Y7!~>6#6#6Å7*|>~2~>*|> ~2>:>z7:>2>*|> ~2>!>6>!>ڰ7*>&v> ~/*>&: w!>4‹7:72"g:^ *:"|> *g:":*9My *9My *9My *~>My *>My **9>"9>\d5͍0C\͏5!Z>s*9>!=8C "9*9*|9s#r͍0C*Z>&\8DM\͔5:j2j\v5:9ҁ1*|9)8"|9:y9ZŠ1a9ҟ10ñ1g9ұ10!_>q.*[> :_>w*[> ~!`>q*[> :`>w*[> *[> ^#VN#FR* *[> 6*[fXXDATA $$$~XXCOMM $$$::;7;YYABS $$$YYPROG $$$YYDATA $$$YYCOMM $$$CPMLDR BPCPM3DR}ے}}}}?FPBNXBXXABS $$$ FXXPROG $$$4_2*l>DM2ͦ3Ê4*[>##l>͞8Ҋ4 *[> ~34_2*l>DM2:n>j4*[>  *[> N#FPY͹8d463g4ͦ3Ê4*[>  *[> ͞8҇41Ê4ͦ3!p>p+q*o>"[>!s>s+p+q*q>DM3*[> ^#V"]>*[> N#F*q>?8*]>:s>w *[> 6!u>p+q*t>DM3*[> ^#V"]>*[>OR$UNRECOGNIZED ITEM $ O}:F|: |1 >My *|>":i`N#Fog_og_{ozg_ogDM!>))덑o|gV8 =D8DM!>))k8 =c8_{ozg^#V) ~8^#V|g}o ˆ8_{ozgi`N#Fogo&og_{_z#W>^#V!=8"b>?8!a>s1!a>P2*[> DMv5*a>M1*[> DM͕6P2*[> DML5*b>!=8MͲ1*[>  *[> ͞8ҍ2*[>  *[> N#Fq#p *[> ~ڮ2*[> DMB5 *[> 61*[> N#F*[> *[> N#F͔51!e>p+q*[> N#F*d>?8^8*[>q#p*[>n;;;;      45*"6""6**6#"*6ú56**6?\ABORTED$NO SPACE$NO FILE: $CANNOT CLOSE$DISK READ ERROR: $DISK WRITE ERROR$YYYP   YP6YPYPYPYPYPYP Ͳ ò!>6#6͐6">*>|$7> N#F*t>?8*]>~   +5{>.+55OͲ5w66ͩ6́5;6<566́5͕6<>́5͕6<>645͜6<H66! w #ˆ5>Ö5>2,6""6"$6yo`"&6!"*6͋6-66*&6|6 "&6*"6MD6*$6DM:,65ͷ6g666Ͱ66**6|6U6*$6GENCOM COMt GENCPM COM GENCPM COM(!"#$%CPMLDR REL&'(DIRLBL RSX )*HIST UTL +,TRACE UTL -.BOOT ASM/01; *;&') N#F:2$!;4%:2$%ͻ2$!;6>!;S*;&/% 6!;48!/%6 !;6#6:; *;&*(~ HҞ*;&*(*;&/% w!;4#4`*;&/% 6.!;6 :; *;&*(~ H!;4#N*( *;&/% w!;4î!;p+q3r*;DLͽ{33yy#q#p#w!!{s#*>6?)@w){#{s333333.;;33,;;#wD{_#6 sO O ڹ.:;=,/[]<>a{Ҷ_#  ý Copyright (c) 1982, Digital Research 11/02/82mpleted.Requires CP/M 3 or higher.1n$1n$" %* %|<Ó* %}0HÓ::$]Ç:$jZÇ:$wÇ:$҄ZÇer ͺv!n$q*n$& ͤ!p$p+q*o$~*o$Nͤ*o$#"o$  ͤ ͤBIOSKRNLASM}23456789:;<=>?@ACHARIO ASM$BCDEFDRVTBL ASMGFD1797SDASMQHIJKLMNOPQRMOVE ASMSSCB ASMTUVGENCPM DATWXYMODEBAUDLIB[e RSX in header. Replacing old by new.Invalid RSX type.No more RSX files to be used.Error on copy.There are not enough available RSX slots.Disk read.Disk write.Total file size exceeds 64K.COM file found and NULL option.No header or RSXs to strip. @ @NULL0LOADER0SCB []=, :;<>%\|"()/#!@&+-*? COMHEXRSX1###~ERROR: FILE: File not found.No directory space.Invalid file name.First submitted file must be a COM file.Duplicate input RSX...Duplicat!r$p+q*q$DMͺ !t$p+q*s$!v$p+q*u$!x$p+q*w$!}$p+q*|$"y$*y$}2$|2{$!~$q*~$&,2$!$p+q*$!$p+q*$!$p+q*$!$p+q*$!$p+q*$!$q*$&-!;6:$!1n$'CP/M Version 3.0COPYRIGHT 1982, DIGITAL RESEARCH151282654321!`i^#V#~#foͽ{¡y#wG:xA##*;&1 :;© :;!;4 !;r+s+p+q+p+q !;6. *;~ *;~2;*;My 2$!;6:$ L :; q#p*'w#6!)" (%͛2$* (##"*<**!<ړ*<&* (6!<4w* (" (!<6*<&') ^#V"(x*(DM͋2$!)"<*<*<&$) N#Fq#px*(DM͋2$:)!)6*<#r*$Ny 2$!L *$#"$ :$$#+";!;6:$!;P *;Nͤ*;#";!;41 !;p+qr*;DMͺ!;r+s+p+q*;DM͗ *;DM͗ *;~w*;*;~!;p+q*;>9Ұ *;~7w÷ *;~0w!;r+s+q+q*;:;~!;H IQ !;60!$6!;6*$#"$;$*$DMi*(DM1%1>!%(z:$/H!"$$#͞%U!$6̓!"<6:"<#ڀ*"<&( 6:"<<2"<_!"<6:$!"<ک*"<&$) >w#6:"<<2"<…!(" (* (:Ow:%/* ( :Ow* ( 6* ( :$w!"$:%:O2)x* (DM *;& w!;4!;6 >!;F:;2;*;&; 6*;& 6!;4!;6> !;ڍ:;2;*;&% *;&; w*;&*(*;& w!;4K;ͫ2$>!$ҥ*'"(!;p+q!;6 >!!;*;&*;6!;4±!!<ڸ*<&: 6!<4!\"<$w#s#r!n"<$w#s#r.:[ -!<6>!:H!<6:+ͱ :;" rͺ :;2 !%6? :;? !%6:$H :$Q :$ˆ :;} rͺ;+ͱ È aͧ !%6:$‘ :$š :$£ *$#";*;Ny 2$ *$DM*;i *:&: w*$##"$ *$;i *:&: w*;"$!:4*$N%͛2$>!$!%"( ):%/i:$R%͛2$*("(!"$$fx%͛2$!"$o!"$*$*$"$/!##"$*$DM*#̓#+s#r!<5&*<$T :{$]*(DMZ!#:Q! <#:Q2<* !0*;"( !;p+q*;DM:O>R*;"( !;p+q*;DMJ2$>!$y*;"( *( >Š*(DMͻO>ҟ*("(!;p+q*$"%*;"%*$"'%̀"$$#*'"( !;q!;6>!;*;&)))=% *;&y 2$\Q *$#"$*$Ny 2$:$1*$#"$*$Ny 2$!L:$IY!M:$YwQ *$#"$*$Ny 2$!N*$#"$9*$0͸ *$#";*;Ny 2$!L:$£!M:$°6*$0͸ F*;0͸ *$DM*;i *:&v: w*$##"$2*$;i *:&v: w* w!$:&<*<-*$**<"*<*$DMi*&<&9) *'<&) N#Fq#p!(<6>!(<ڋ*&<&)))9 *(<& *'<&)))9 *(<& w:(<<2( !4<ڱ"!*3<&ͮ#% *4<& 6:4<<24<…" *$&$ :3 !6<#*5<&*7<*6<&*( ,<* (#^#V"0<:$5~ *( 6x*(DM͋2$!0<#"$%͛2$*$DMi*0<"$/>>!)" (* ( ~2$ʃ҃* ( :$* ( w*("(* ( >Ҭf %͛2$:$~!"$$!"$$#*$"$*(DM1͞%U̓!)"<:4<<24<£R"*'"(X">!$҉!!$6!3<6:$!3< !*3<&') ^#V"(X#/b 'Ͳ"!*3<&% >x *3!$Ҙ Ͳ"!:3<<24<:$!4<!*4<&') ^#V"'!6<6>!6< *6<&*(*6<&*' :6<<26<¿ Ͳ":4<<24<&9 6!(<6>!(!%< *%<& * (*$<&)))9 *%<& {_z#Ww:5<<25<:6<<26<"!: !6:5<<25<:6<<26<:#>i`N#Fog_ogDM!>))덑o|gҨ# =–#DM!>))ҽ# =µ#^#V) #^#V|g}o #O{ozgi`N#Fogo&og_ (*("(!"$:%N:%/!$N!)6 *( 6*(DM͛2$:$H !"$:%1:$d~õ:$ʚ x*(DMZ:$ʚ:{$$͂#+s#r*(DMZy:{$$͂#+s#r!$#+s#r*(DMU:$/1*(DM1x*(DMͦ*(DM*(DM͋2$.)$ -:%Ÿ :3<<23<0 !$:$ !9!3<6!$:3<҄!*3<&$ ~24<:$=2$:4<26<:$!6!$ҹ! !O:) ":$!!$6!:%!%!!$6!!$6:)"!$6.;) w:%<<2%<!)" (!$6!,<6:$!,<*,<&$ 6!-<6:$!-<ں*-<&') ^#V"(!.<6>!.<ڑ*.<& * (*.<& *(ʇð:.<<2.!$:$_!)" (!,<6:$!,<r:,<<2TEMP $$$R#/:%/>!%**(DM*O>S:%/P o:%o*( >o :% :$<2$23<!*3<&ͮ#% *3<&') q#p!4<6:$=!4< !5<6> !5<:3<=o&!ͮ#% *5<& !*3<&ͮ#% *5<& w:5<<25<³:3<=23 !)6:O2) *( 6*(DM͛2$:$1 *(DM1!"$!3<6>$#_"*(DM͠*$~[h*( ~25<>!5<!6<6!4<6:5<=!4<*6<&*(*3<&)))=% *4<& w:6<<26<:4<<24<†*3<&% :5 !VHҽ >!VҸ :V2Vý !V6!V:V *V^*V&+S*V& *Vq !V6*V6ͧ * Cold Boot $Number of console columns $Number of lines in console page $Backspace echoes erased character $Rubout echoes erased character $Initial default drive ($:) ? $Top page of memory $Bank switched memory $Common memory base page $Long error messages $!Vr+s+p+q+q:V *V*VDM*V -- !Vs+p+q:VJ *V*VM!VLS!Vq:V e > :Va/>z!V/H҄ :V_2V:V!Vq:V/>!V/HҦ >ͧ>!Vp+q(7*V~ Y7 N7NTe:T *TMV Y*Vw!Vq:e: $ Base,size,bank $Zero length segment not allowed.$Bank one not allowed.$ ERROR: Memory conflict - segment trimmed. $Memory conflict - cannot trim segment.$ ERROR: Memory conflict - segment trimmed. $ ERROR: Memory conflict - segment trimmed. rch *** CP/M 3.0 SYSTEM GENERATION DONE ***$!Tq:UM*T&!Tp+q:Ud*T !Tp+q*T#6:UҀ:Tڀ*T *T#N! *T6 7 7!Tr+s+q+q!U6N*TDMN:TTN͜:T.:T/!U!]6 !m6 !Tp$Double allocation vectors $Accept new system definition $ CP/M 3.0 System Generation Copyright (C) 1982, Digital Research $ BNKBIOS3 SPR$BIOS3 SPR$BNKBIOS3 SPR$BDOS3 SPR$RESBDOS3 SPR$BNKBDOS3 SPR$ 64K TPA Copyright (C) 1982, Digital Resea1TdCP/M Version 3.0COPYRIGHT 1982, DIGITAL RESEARCH1512826543210123456789ABCDEF ERROR: $Reading file: $Writing file: $Directory full$Reading file: $Writing file: $Invalid drive.$) ? $) ?VO! N7:VO! N7!Vp+q 7*V|O *V}O H7!Vq*V&+SDM$ !Vp+q!V6!V60!'"V>V͇S† *VM7 !V6>!V VVzSڽ !V6:V<2VVVzS+s#rÔ :V *VM7!V60*V! S"V:V<2V‹ !Vs+q(7:V  #7$ CP/M 3 Sys $ Memseg No. $ Bank $ Accept new memory segment table entries $Default entries are shown in (parens). Default base is Hex, precede entry with # for decimal $ Use GENCPM.DAT for defaults $Create a new GENCPM.DAT file $Display Load Map at+q *T 6 *T 6*T!Tp+q*T!Tp+q*T!Tp+q*T] ͧ!Tp+q*T} ͧ!Tp+q*T ͧ *T 6!Tp+q*T!Tp+q*T! ͧ!Tp+q*T" ͧ!Up+q*Tetting up Allocation vector for drive $ Setting up Checksum vector for drive $ *** Bank 1 and Common are not included *** *** in the memory segment table. *** $Number of memory segments $ CP/M 3 Base,size,bank ($) $ Enter memory segment tabl $) ? $Bad character, re-enter $ $ Disk read error: $File cannot fit into GENCPM buffer: $Unable to open: $BDOS3 BIOS3 Setting up directory hash tables: $ Enable hashing for drive $: $Unable to allocate space for hash table.$ SV6? ͜*VDMN*V~  (7*VN !V6>!Vn *V#"V:V:-Q/HX *V6d ,7*VN :V<2V, *V++"VNÊ *VN*V !V6!V6Te!Vr+s+q:-Q/Ү >!V6#q#p!V6:5Q!Vڳ*V&+SFQ  VzSک:VM*V&+SFQ !V6>!V8*V&NV) >w#6*V&pV) >w#6:V<2V:!Vڡ*V&)*&V>͒Sʗ*V&)*&VWR"(V *(V WR"*V*(V ͕SN:VAO7:7!V6**V ^#V!S*V&+S*V&NV) q#p*p+q%N*VDMN 7*VDM$  7*VME :,QҨ *V&U *VDM :V 2V*V&U DM*V:V2V*V&U *V&+S:V2V*V&U ) :V2V!Vp+q*V"TͣN,ͧ*VDM !Vr+s+p+q*V^#V"T*V##^#V"T*V ^#V"T2T:T=2T* U|O:T2TҮ:-Qқ*nV*U*V |!UO:/Q2T*U|O:T2T2Uͬ:U/Ҙ!!V6>!!Vژ*!V&$SQ  6:!V<2!Vsà!U6:V/ҫ*:U2T:T2TTͩ:-Q*T&+SDM*U*T&+SDM*U:-Q/*V&)*&VWR"(V*V&)*&V>͒S*(V S?!V6*(V ͕S:V/c!V6N:VO!=R ~2T *(V WR"*V**V N#F`i))"VN:VAO7N*V&6Q DMʹ ͜*V&6Q ~/*(V q#p:-Q/!V6*V&,V) *Vs#r*V*L *V w*V}O! *V w*V}O! *V w!T:TO`iPSW "V*V :0Qw*V :2Qw*V :1Qw.*V :3Qw*V :4QwX*V   :+Q/ҼW*V >*V w:@*V wW*V >*V w^*V :/Qw!)X"V* ~*V&+SFQ  VzSHJ:V2V*V&+SFQ  ^#V"Vé*V&+SFQ  ~*V&+SFQ  VzSHҩ:V2V*V&+SFQ  ^#V"V:V<2V¿ :V:VH`!V6:5Q!V`*V&+SFQ  VzS/*V&!Vs+6:V!V4>T͇S+s#rBKͧ pT^ :V<2VpT *VT :-Q/k)Tw T z!LT"V!U"V͙!T"V!U"V͙!(T"V! U"V͙*V#DMT  *VDMT *VDMeͧWͧ *VDM> *V*Ws#r*V##*Ws#r*V*V#DMT  *VDMT *TZSU͊S@?ͧ*T+ZS}<2V!V6!V:V҆*V&+SW "TDMͧ *VDM> :V<2VS*TDMO W*T"T!Vr+s+q:VGTqT TyT *Vn}2T*V#~2TpT WTS}pS}TR+s#r*V&)+&:U2!V!""V*!VM"V͟:!V2U! U6Û*U|!U2!V* U|!Uo&)##""V*T&+SDM*!V*!VM"V͟:!V2 U:U2!V!""V>T͇S+s#r*!VM"V͟:!V2U* U|!$V2T:T2T U(T(TͩC*$V&+ST͊S+s#r* U|!$V2!V:-Q/ *T&+SDMV"LV*V͛ 2V'ͧ*V&+SFQ  *(V w*V&+SFQ N`iPS*V&+SFQ  N`iPS*V&+SFQ  ͕S *(V q#p*V&+SFQ  VzS*V&+SFQ  q#p:V<2V:-Q/!V!$V6:T<<2T:T<<2TVN#F!W "V*V"V*V͕S(!$V6-!$V6*VSD*VWR!"&V!V6&VS!V6>!Vڷ*V&)*&V>͒Sʭ*V&)*&VWR"(V*(V ͕Sʭ!V6:V<2Vf:-Q/!V!$V6!$V6V>X W*V"V*V~>>!Vs+p+q++SFQ  ~H*V&+SFQ  VzSHV:V2V*V&+SFQ  ^#V"V:V<2V:V!$V6!U6ͬ#Q$!H> U͇Sʔ* U|2Uß*U|2U!U:.Q2T*U|!UO:/Q2T*U|O:T2TUTI:-Q/!$V>O:T2T* U|O:T!$V *Ws#r*VDM> !V6&VS(>!V6>!V*V&)*&V>͒S*V&)*&VWR"(V *(V## *(V ͕S*(V ͕SH*(V ͕SH*(V ͕SH*(V ͕SH!V6:V<2V-:V!V6!V6!V6>!V!U q:V 2V*T&+S"!U$-U RUW !T6#6#6:.Q2U:/Q2UTqT TyT Uͧ pT !T6Uͧ pT pT :;Rһ!;R6:%V2.Q:4Q/24QTT TT L!U6N!Vr+s+p+q*V6 *V#6 *V|O! *V## w*V|O!*!V"*T&+SDM*!V*!VM"V͟:!V!Uw:-QҢ!T6:T2TULTLTͩ*U|2!V*U|!Uo&)*"V""V*T&+SDM*!V*!VM"V͟:!V! Uw:,Q/Ҳ:V2V *V&U  :T2T*T&! S!0*V& U q*T&! S0*V&V&NV) nVR+s#r*(V ͕S—'N:VAO7:7!V6**V >R!S*V&pV) s#r*V&) VR+s#r **V R*V&pV) CS **V q#p:V<2Vk:Vҫ͜:T2FQ!T:/Q2GQ!"IQ!HQ6!V6ON:GR2T 5Q N*FQM ,7*GQM ,W&W) N#Fq#p*W&+SFQ  *W&7W w!W4+:-QF,!fW6K,!fW6 !W6:W4:fW=2iW!"gW"dW}2 W! W6*T&PS*LViS"bW:-Qڞ,nVbWzS*ViS"bW!W6>!W,*W&W) *W&+SKQ  N#Fq#p*W&$SQ  6!W4£,!W6! W6#6!W6n&d value in the DPH directory BCB address field.$ Setting up Blocking/Deblocking buffers: $ The physical record size is$: $ *** Directory buffer required *** *** and allocated for drive $: *** $ Overlay Directory buffer for drV:V/+~!V/H+ |ͧ!V6 :V!V+~!VHc N*V&+SFQ :Vw!V6 :V!V+~!VH N!V:V*V&+SFQ  Hq!V:VO`iPS*V&+SFQ  q#p!V6:V<2V×1:V<2V"͜!V6:5Q!Vo!:V!t new buffer definitions $!W6>!W**W&)*&V>͒S**W&)*&VWR"(V ͕S*(V ͕SHҸ* *(V WR"*V**V ^6 *W&$SQ q#p*W&$SQ  6*(V ͕S*%ͧ!W4*!W6>!W+!"HW}2W>!W=+*W&W<2W#!V6*V&U  !V6TqT TyT Wͧ pT^ pT^ WS#ZS"U!W6>!Wڋ$*W&,V) >w#6:W<2Wh$!"LV:]A$!U6#6!W6>!W$*W&=R 6:W<2W¦$$!U6#6:mD$!U6!T6 Available space in 256 7*HQM N:V/҈!N!V6:5Q!V !V6:V/ :V =O!=R ~2T*V&+SFQ DM *V&+SFQ  N`iPS*V&+SFQ  q#p*V&+SFQ  ~ͧ *V&+SFQ  ~7ͧ *V&+SFQ ~2V*V&directory buffers reduced *** *** accordingly. *** $ Share buffer(s) with which drive ($:) ? $ *** Data buffer required and *** *** allocated for drive $: *** $ Overlay Data buffer for driveive $: $ Number of directory buffers for drive $: $Minumum number of buffers is 1. $ Number of directory buffers for drive $: $ *** Maximum number of directory buffers *** *** for the current drive is$. *** *** Number of N!N:V=O *V&+SFQ NE *V&+SFQ  NE :-Qb!N*V&+SFQ  N ͜:V<2V !T6!V6%NVʹ ͜PNT2V!TT TT N!V6Vʹ ͜:V!FT !!U6+6!W6͌!:W/җ#:R2T͜$SQ HW|S ~H6+*W&$SQ ^#V"HW!W4**W&))lW *HWs#r*W&))  >w#6!W6>!W+*W&$SQ HW|S>͇SH+*W&))lW  *W6 DS+s#r*W&$SQ  6!W4h+!W4*!W6>!W7,*W&+SFQ  *byte pages: $TPA =$, Bank 0 =$, Other banks =$Unable to allocate Dir deblocking buffer space.$Unable to allocate Data deblocking buffer space.$Unable to allocate Data deblocking buffer space.$Drive specified has not been defined. $0FFFFH is an invali*V&+SFQ  N "V*V|*V}O:/QH҆MN!V:/Q*V&+SFQ  Hq!V:/QO`iPS*V&+SFQ  q#p *V}2V!V6!V6!V:V# *V&+SFQ ~2V*V&+SFQ  :V2V*V&+SFQ  *V&+SFQ  ! $: $ Number of data buffers for drive $: $Minumum number of buffers is 1. $ Number of data buffers for drive $: $ Share buffer(s) with which drive ($:) ? $ Allocate buffers outside of Common $ AccepPS"U:DR2TN-Qʹ ͜:-Q/2T:-Q[#:ER2T/Q ͜:FR2TN+Qʹ ͜x#:R2T͜N!W#*W&U 6:W<2W#!W6>!W $*W&U 6$:N;Rʹ :=R2T͜͜N,Qʹ ͜͜:>R2T:2Q<22Q  2Q :2Q=22Q:?R2T:1Q<21Q' 1Q :1Q=21Q:@R2THN3Qʹ ͜:AR2TkN4Qʹ ͜͜:BR2TN:0QAO7NTe:T"*TMV A2W*WM͈ /"Þ":W20Q͜͜:CR2T.Q *.Q&))lW  ^#V"JW*W&))lW >͒S:WH3:WE-1&N!W6]&N*W&))lW N#F$ {&N!W6>JWR>fS:WHҚ-!JWVS+s#r!W4g-!JWVS+s#r:W3*W&)*&VWR"(V WR"*V >RZS"^W **V ͕S-!W6-!W6WS<*W&+SFQ  2W!FQ  ~:W!WHL<:W2W:W2W!W4;:T2FQ!T:/Q2GQ:W<*W&+SFQ  O:T<*W&+SFQ  N`iPS!͕S"`W!FQ :T w*W&+SFQ  N`iPS*`WiS!q#p!W6n&))&PS*U "ZW*RW "VW*T"`W*`WW !T͕SC6*`WW 6*`W#"`W6!W6n&))lW  ^#V"JW*W&))lW >͒S:WH9!W6>JWR>fS:WHҶ6!JWVS+s#r!W4Ã6!JWVS+s#r:W8*W&)*&VWR"(V*W&$SQ  >«7*W&$SNTe:TL0*TMV A2 W* WM͈ *0/* WMF80/*W&$SQ  : Ww͜c0*WMTCc0 4*(V ͕Sn3!W6*W&$SQ >͒S°0*(V q#p*W&$SQ  6n3bB*W&$SQ  >w:-Qګ1: W1:W1! W6!W6*W&$SQ  6(N:W6>!W::*W&W) *W&+SFQ  N#Fq#p!W4:*V*RW*nV "RW> U͇SUzSH҇:*TW*U|O:.QO:T2Uá:*TW* U|O:.QO:T2U!U:T2T:T2T:T2T:.Q2.Q* U}pS} URU͊S"`W> U͇SUzSHB;*RW)NWʹ ͜P,!"PW}2Wo&"TW2W>!Wu5*W&$SQ  ~n5*W&$SQ  ~ >Hһ4:-Q|4!W4á4*W&$SQ !^N#F-S*TW"TW*W&$SQ  ^*PW"PW*W&$SQ  ~ >Hn5:-Q/5!W4*W&$SQ *(V ͕Sc0bB*W&$SQ  >w:-Q.: Wd.! W6*W&$SQ  6&N:WAO7&N.:W{O!=R ~2T&N:WAO7'N*W&$SQ  DMʹ ͜*W&$SQ  ~.*W&$SQ  6.*W&$SQ  6t/:W;O!=R ~2T'N:WAO7+s#r*(V *ZWs#r:fWZWR+s#r:fWjWR+s#rã8*(V"LW*W&$SQ  >o&)*&VWR"(V!Q  >ʂ8*(V ^#V"NWÐ8*(V ^#V"NW*LW"(V *NWs#r!W4>JWR>fS:WH8!JWVS+s#r!W4ç8!JWVS+s#r6!W4n&))lW  ^#V"Q  ~h7*jW6 *jW *VWs#r*W&$SQ VWR+s#r*(V *ZWs#r:fWZWR+s#r:fWjWR+s#rë7*(V"LW*W&$SQ  n&)*&VWR"(V ^#V"NW*LW"(V *NWs#r*W&$SQ  >£8*W&$SQ  ~48*jW6 *jW *VWs#r*W&$SQ VWRWAO7(N1: W1!W6! W6:Wʨ1:WƋO!=R ~2T(N:WAO7)N*W&$SQ  DMʹ ͜*W&$SQ  ~ґ1*W&$SQ  6è1*W&$SQ  6! W6S2:WKO!=R ~2T)N:WAO76)*W&$SQ  DM  *W&$SQ  >w: WS2|O:/Q2T*U}pS}URW"\W*T&PS"XW*T&PS*U "VWÇ;*RW*`W|O:/Q2TW*U"\WO`iPS*`W "XW*T&PS* U "VW*RW*\W"T*U|O:T2T*W&)*\W"jW*XW"ZWWTS"U*T"`W*`WW !T͕S;*`WW 6*`W#"`W;!W6!W6!W6:5Q! ~,5*W&$SQ !^N#F-S*TW"TWT5*W&$SQ !^N#F-S*TW"TW*W&$SQ  ^*PW"PW!W4#4*fW&*PW+S*W&) "RW:-Q9W*U"jW*RW*U*TW *LV *V *nV |O:.QO:T2UO:T2T:T2T:T2T|2U!T2.QW"T*T>'*W&$SQ  DM  : Wt/! W6*W&$SQ  ~t/A'ͧb'N:WAO7'*W&$SQ  DM  &/*W&$SQ  ~^W͇Sҹ/'N*^WDM$ 'N*W&$SQ  *^Ws*W&$SQ  ~R0:W[O!=R ~2TM(N*W&$SQ  ~AO7(JW\6!W6>!Wc9*W&,V) >͒S\9*W&)*&VWR"(V *VWs#r*W&,V) VWR+s#r!W4 9!W6>!W9*W&)*&VWR"(V*W&NV) >͒Sʽ9*(V *VWs#r*W&NV) VWR+s#r*W&pV) >͒S9*(V *VWs#r*W&pV) VWR+s#r!W4h9aB!  : Ww͜*W&$SQ  :Wwn3:U!W]3:W+O!=R ~2T)N*W&$SQ  DMʹ ͜*WMTCn3 4! W6*W6 dWDS+s#r!W4>JWR>fS:WHҿ3!JWVS+s#r!W4Ì3!JWVS+s#rç-!W4n&))lW  ^#V"JW-!T6!W6:W 4bB! W6*W&$SQ  ~S29)ͧZ)N:WAO7)*W&$SQ  DM  2*W&$SQ  ~$3: WҌ2! W6*W&$SQ  :Ww 3:WkO!=R ~2T)N*W&$SQ  ~AO7)NTe:T 3*TMV A2 W* WM͈ 2Ü2* WMF2Ü2*W&$SQlW  ^#V"JW*W&))lW >͒S:WHғA!W6>JWR>fS:WHh=!JWVS+s#r!W45=!JWVS+s#r:WxA*W&)*&VWR"(V*W&$SQ  >0?*W&$SQ  ~>*(V"LW*W&$SQ  n&)*&VWR"(V ^#V"NW*LW"(V *NWsL>:WWͧ T. T~ !W6!W6>!WN!W6#n& +S P  ~2W!W6:W:W/H N!W6>!WڞL'N *W&+S P *W& *W&W w!W4gL:W°L!W6L:WL:WA*W&W wL:W L:W0*W&W wL:WA *W&W w'N*W&4D>!Wq*W6 dWR>fS'F>%ͧ>ERROR: $ at line $Missing parameter variable$Equals (=) delimiter missing$Invalid drive ignored$Invalid character$Invalid parameter variable$!"WWͧ !W6!W6:W GG:WG͈K2W:WFIG@*W&$SQ ^#V͛ 2W*jW6*W&+SFQ N`iPS!N`iPS!͕S  *jW q#p*W&+SFQ   *jW w*W&+SFQ  *W&$SQ |S+s#r@*jW6 *jW *VWs#r*W&$SQ VWR+s#r *jW 6:fWZWR+s#r *jW s#r:fWjWR+S P  ^*W&+S*W"W*W&T ~?[J *W&+S P  :WO!=R 6!U6!W4!T5>!T҇K:WʧJ*W&T ~A/>P/HҜJ*W&T ~A*WwäJF GÇK:WJ*W&T ~Y*WwÇK!W6*W6!W6:T=!WڇK:W!WO!T ~2W, K*W#"W6 2W!FQ  ~:W!WH0D:W2W:W2W!W4C*W&+SFQ  S+s#rcD!fW:iW2iW*W͛ 2W…D4%ͧ>äD*W&+SFQ  WzS+s#r!W4±CF*W&$SQ  ~2W!W6:W!WF!fW:iWoE!iW6*gW#"gW!W6!W6!W6:5Q!WME#r0?*\W*ZWs#r*(V *XWs#r*XW##"XW*\W##"\W!W6*W&$SQ  ~!W ?*W&$SQ ^#V͛ 2W*jW6*W&+SFQ N`iPS!N`iPS!͕S  *jW q#p *jW 6*W&+SFQ  *W&$SQ |S+s#r:fWZWR+s#r *jW s#r:fWjWR+W/:W/HI!W6>!W/H*W&W 6 !W4HtG2W!W6:W:W=H:W H:W/H~H*W&W :WwtG2W!W4:H:W=:W H:W/HҧHtG2W~H:W I:W=>!WHH!W6 I:W=HHF GH:WHcF G:W :W/HF GF!Wr+s+q:U2W!U65FN*WDMN>FN*WDMZ :WCG.͜:W2U:WoG!W6TlG!W6sG!W4MG*W&W ~2W:W :W H:W HG:W ·G*W#"WMG*W&W ~2WÄG:Wa/>z!W/HG:W_2W:WG!W6:W!W6:+s#r!W4?:fWjW͇S+s#r! >w#6:fWjWR+s#r!W4>JWR>fS:WHhA!JWVS+s#r!W45A!JWVS+s#ru=!W4n&))lW  ^#V"JW=!W6>!WA*W&7W *W&+SFQ  w!W4˜A!W6>!WaB*W&)*&VWR"(V*W&NV) >͒S"B!W6ÀK:W#K!W6 ÀK:W02W:W> !WHQK>!WLK:W2WQK!W6!W:WxK*W^*W&+S*W& sÀKF G!W4J!W6!W6:W:W/HK!W6:W *W&+S P *W& *W&W HK!W4éK:WK!W6K!W4ÒK:W*W&+SFQ  2W!FQ  ~:W!WHFE:W2W:W2W!W4D*W&+SFQ  S+s#ryE!fW:iW2iW*W&$SQ  ~ڼEWbWzS+s#rYS:/QpSҹEd%ͧ>E*W͛ 2WE%ͧ>E*W&+SFQ  WzS+s#r!Ws#r!W46>:fWjW͇S+s#r! >w#6:fWjWR+s#r*W&$SQ  >1A*W&$SQ  ~¤?*(V"LW*W&$SQ  n&)*&VWR"(V ^#V"NW*LW"(V *NWs#r1A*\W*ZWs#r*(V *XWs#r*XW##"XW*\W##"\W!W6*W&$SQ  ~!W A*W&$SQ  ~ ItG2WHGtG2W!W6!T:W:W H:W/H[I*W&T :Ww!W4~`i+wtG2WI:W :W/HxItG2W[I!W6#6>!W҇K *W&+S P  ^#V"W! P  ~2WJ:WI:WA2WI:W0/>9!W/HI:W02WI:WA 2W *W&N*WDM$ :U C$%N*WDM$ >W͇S>W͇SHHC!W6MC!W6͜͜!Ws+q*W&$SQ ^#V"W:-QڋC:fWWRbW͊S+s#rF!iW55:W®D*W&$SQ  ~2W!W6:W!WګD!fW:iWYD!iW6*gW#"gW!W6!W6!W6:5Q!W7D*W&+SFQ  *(V *ZWs#r*W&NV) ZWR+s#r*W&pV) >͒SZB*(V *ZWs#r*W&pV) ZWR+s#r!W4A!"W"W!W6:5Q!WB*W&+SFQ  ~¶B*W&+SFQ  VS*W"WB*W&+SFQ  VS*W"W!W4pB$N%N!bWVSDM$ :-QMC%W 6 'N*W&W 6='N*W&W 6  *W&+S P  !^*W&+SR"W:WmM'N*W~A*W&W wM:WʞM'N*W~ҐM*W&W 6YÛM*W&W 6NM*WNbN:WM'N*W&W 6,*W#"W*WNbN'N*W&W 6,*W#"W*WNbN'N*W&W 6 'N*W&W05O#+v: s خSx:q$Of`R(Ԅ.- ͼ{>X0Y""f@VmjYVlUyBlڰ :0rP1nʲLJ5cAU %Ja`ͼ` `@k+T$ dp#t f`C՛V]b3jH6'p0!!*WH|#+x[݀:a v@D24D) #: Id ynјY)AB@h(P&!r7Bi6L@r2L@3%0h(H @P( @P( @P( !Xf. rfi3A R G!`i3N`e9L'#  Cd l [ -"ڴ#+[p[@PRTMSG ,QPAGWID 2QPAGLEN 1QBACKSPC 3QRUBOUT 4QBOOTDRV 0QMEMTOP .QBNKSWT -QCOMBAS /QLERROR  +QNUMSEGS  5QMEMSEG00 KQHASHDRVA6QALTBNKSA +QNDIRRECA ;QNDTARECA KQODIRDRVA [QODTADRVA kQOVLYDIRA yI ;6 pfiEt(Ub F$ [@{m8A8upBk !W NT^ T :W]NT^ !W6>!WUN*W&W 6!W4:N!W6aN!W4!Wq'N:WO! *W&W w'N:WO! *W&W wO*TDM}oN*T†O]!O> 2 PW:TgxʀO { O: PO*T!v;cv8-Vx ͡LȆ?쁣@¶CVK'%dm]0p@" _2lR{6݁0Xw< M"0xʄGAD"!< "Ce6LgA!@r6а0 f a0 f f'/v{BH»@Y{La0`5;l:JfѰՐ^b1b+$ ^Ȋ l9O/J7ps[F՛/xFV][^+vz@W ]+z@t"^+zEW Tz@W ^+z@W ^+z@W ^)jcv;cv;cv;cv;cv;cv;cv;cv;c{QOVLYDTAA QCRDATAF ;RDBLALV g>:N ,:h : Rxf0V jo<- 'i0)d`@!M#%y`ݒ{JI;%%Ydn0ڄ-V<|fހfQfݠ6m]YmrXHk!W!*UC6(9``* º`+`1YbGV ^G< E`Y jV_0HSPhhP8ͱ HFlh8` nx*l6ǀ3ll8 ~ `4fPp$#`?ٶ4u`Lͮ`eU8kFo&ePJܮwXڮVmfP DJ¯@ pic@Y FՀ3lh #~K6ƀHP&Y)AO†O~#o}o|O<O:TzO<.O:TƜzO<8O:TzO:TzO:TotOzO:TgN!|!|#b1En6`  fԐ1Uum(@8"ͩ bT|Ёnʲc`ݒͣJU;$wgvHea͵@lNd6Xt\ Ux&m&bsgHdf(eaUpW }IGÕAV!I@.1[|V!K'ԙ4yL6#Fr8#* Jj\U +ͣMU9Lg!DM!>))덑o|gS =S^#V))) DM!>)):S =2S_og^#V) PS^#V|g}o ZS_{ozgO{ozgi`N#Fogo&og_{_z#Wi`N#Fog_og_og?쁲[*@`^2K6meRq}Bwٴj^2! ;4f@RzKƬ;ͽ~ â:!~mU0wz@uB@+͵͸ja] mfݠ6ma`Q2XCp̃\Ub4f07 JYM"3i(2GV ew*a q='@DuO#?(W >*\ ERROR - FORM IS X,Y TYPE HISTOGRAM BOUNDS HISTOGRAM: ADDR RELATIVE FREQUENCY, LARGEST VALUE = .INITIAL = .COLLECT = .DISPLAY = .... !6 ` !6 ` !6 ` *&T` !6 ` !6 ` !60 ` *&DD  $$HD@" @@ $B $$H$H$HH$$! HD$D$D@AD HD$!A" KUw(A^Od`@F*K՛v#ץf@#sFI'ëYALPSID'TCELLOC$LAITINI!%cCOPYRIGHT (C) 1977 DIGITAL RESEARCH {{ { {zb{b{*9 {_zW}l&))o> \> \\ß*"!" ͟#͟Prںºx"x#"̀ں͇"1!6# y~:2>2:<** "_?:<2>!/:<}:2* ~b W6 y2> # vwm>2>!/ N *~O²+—">2>!/*:< "~G # p *~w#  :;k+6 ~PV BP@2!~sǣ+t9erl[U;D +Wx z2AEwvlfuhٶI,V f`CMa 2YMWx!y@b+ó`@ @-U Uw[AF: c6B*OU > 0"[-Ke%ـl͟!h͟$h͟'h*̀`*̀`*1̀I ?! ^#Vr+sz`>>!@^#V#̀{ k͇#"/<͟h2**̀`i~#!~6͟*1Þ6͔h*1^#V#Þ͔{> \*/ *8*:*8yO:O*}O= ~ w#P^#V#ɷ{ozg |g}oh:<͉̉O<OBKBK$'-*!*Dp"[<-Ki%pm@D"[T-Kl%A@mD"[n-Kn%ЉmD"[-?帡`n@D$"[-Ks% {tX$@UaUzjH+{P@3k(3jK4K6`JYG&ml fհmIW, x@(dz¦.U _6J X4!y~=W!x# ~#bxE {8~#o}oA'.`28!Ip+q*HT!J6J T ` T!p+q*T> >/Ҥ×!p+q*DM͛:̀ ̀:2:!!K:*&L Ǹ!4!K6 ͐utIw!/>!/>!*6 #:_#:*Y" Y" Y" "*Y"#####Y"##Y"Y"Yz2*Kg"ɯ22!"*DM6:O* 2~ ~ †:<DIRLBL yd'* !9"1"#2#:Og}**Ip2~w2i#1#":RͶ :O~!ʫ:<2Ž:"2"x2*# O:ļ:<:G>O*# :<t T` !6* ` !6* ` !6* ` *& @AA I$DBD $I$BHA"DH!""@ jmp out$blocks cseg ; boot loading most be done from resident memory ; This version of the boot loader loads the CCP from a file ; called CCP.COM on the system drive (A:). ?ldccp: ; First time, load the A:CCP.COM file into TPA equ 5 if banked tpa$bank equ 1 else tpa$bank equ 0 endif dseg ; init done from banked memory ?init: lxi h,08000h ! shld @civec ! shld @covec ; assign console to CRT: lxi h,04000h ! shld @lovec ; assign printer to LPT: lxi h,02000h/ ͩ!4¡ :$ !4!"%!q: O !{4>!O :!{O :2*'M!8 ^#V%!t ͫ *%B :w*%#"%` Ø Ø Ø Ø Ø ͩ` *M6` !6 ` !6 ` !6 ` *&T` !6 ` !6 ` !60 ` *&!y~=W!x# ~#bxE {8~#o}oA'.`28!Ip+q*HT!J6J T ` T!p+q*T> >/Ҥ×!p+q*DM͛:̀ ̀:2:!!K:*&L Ǹ!4!K6 ͐u ! shld @aivec ! shld @aovec ; assign AUX to CRT1: lxi h,init$table ! call out$blocks ; set up misc hardware lxi h,signon$msg ! call ?pmsg ; print signon message ret out$blocks: mov a,m ! ora a ! rz ! mov b,a inx h ! mov c,m ! inx h outir @@ I$B$!!D!$"H@* ͡. ;ͣW!E# ¡ # ¬# ·@ʴʥzʖ=ʐ=|zJz?4)z z title 'Boot loader module for CP/M 3.0' true equ -1 false equ not true banked equ true public ?init,?ldccp,?rlccp,?time extrn ?pmsg,?conin extrn @civec,@covec,@aivec,@aovec,@lovec extrn @cbnk,?bnksl maclib ports maclib z80 bdos l!F2y* "*xT-V-^yA!~4x]> WO" Q>2y*"  INITIAL = COLLECT = DISPLAY = "-A" IN EFFECT, ADDRESS BACKTRACE READY FOR SYMBOLIC BACKTRACE BACKTRACE:%B 2!4þ *%"%:ÇYALPSID'TCELLOC$LAITINI!ÓCOPYRIGHT (C) 1977, DIGITAL RESEARCH g gzd{ *9 Wl> W> W*"!"^l!]kl$]xl']::>2l!6!"!~4*s,r,"!~O xra a ! sta ccp$fcb+15 ; zero extent lxi h,0 ! shld fcb$nr ; start at beginning of file lxi d,ccp$fcb ! call open ; open file containing CCP inr a ! jz no$CCP ; error if no file... lxi d,0100h ! call setdma ; start of TPA lxi d,128 ! call setec ; print message, print number from 0 to 65535 public ?pderr ; print BIOS disk error message header maclib modebaud ; define mode bits ; External names for BIOS entry points public ?boot,?wboot,?const,?conin,?cono,?list,?auxo,?auxi his is the invariant portion of the modular BIOS and is ; distributed as source for informational purposes only. ; All desired modifications should be performed by ; adding or changing externally defined modules. ; This allows producing "standard" I/O ; restore original bank ret no$CCP: ; here if we couldn't find the file lxi h,ccp$msg ! call ?pmsg ; report this... call ?conin ; get a response jmp ?ldccp ; and try again ?rlccp: lxi h,0100h ! lxi b,0C00h ; clone 3K rl$1: mvi aextrn @ctbl ; physical character device table ; disk communication data items extrn @dtbl ; table of pointers to XDPHs public @adrv,@rdrv,@trk,@sect ; parameters for disk I/O public @dma,@dbnk,@cnt ; '' '' '' '' ; mem,p$zpio$3a,0CFh,0FFh,07h ; set up config port db 3,p$zpio$3b,0CFh,000h,07h ; set up bank port db 1,p$bank$select,0 ; select bank 0 db 0 ; end of init$table end multi ; allow up to 16k bytes lxi d,ccp$fcb ! call read ; load the thing ; now, ; copy CCP to bank 0 for reloading lxi h,0100h ! lxi b,0C80h ; clone 3K, just in case lda @cbnk ! push psw ; save current bank ld$1: mvi a,tpa$bank ! caff in common memory ; variables in system data page extrn @covec,@civec,@aovec,@aivec,@lovec ; I/O redirection vectors extrn @mxtpa ; addr of system entry point extrn @bnkbf ; 128 byte scratch buffer ; initialization extrnmodules that ; can be combined to support a particular system ; configuration. cr equ 13 lf equ 10 bell equ 7 ctlQ equ 'Q'-'@' ctlS equ 'S'-'@' ccp equ 0100h ; Console Command Processor gets loaded into the TPA cseg ; GENCPM puts CSEG stu,2 ! call ?bnksl ; select extra bank mov a,m ! push psw ; get a byte mvi a,tpa$bank ! call ?bnksl ; select TPA pop psw ! mov m,a ; save the byte inx h ! dcx b ; bump pointer, drop count mov a,b ! ora c ; test for done jnz rl$1 ret ory control public @cbnk ; current bank extrn ?xmove,?move ; select move bank, and block move extrn ?bank ; select CPU bank ; clock support extrn ?time ; signal time operation ; general utility routines public ?pmsg,?pd title 'Root module of relocatable BIOS for CP/M 3.0' ; version 1.0 15 Sept 82 true equ -1 false equ not true banked equ true ; Copyright (C), 1982 ; Digital Research, Inc ; P.O. Box 579 ; Pacific Grove, CA 93950 ; Tll ?bnksl ; select TPA mov a,m ! push psw ; get a byte mvi a,2 ! call ?bnksl ; select extra bank pop psw ! mov m,a ; save the byte inx h ! dcx b ; bump pointer, drop count mov a,b ! ora c ; test for done jnz ld$1 pop psw ! call ?bnksl ?init ; general initialization and signon extrn ?ldccp,?rlccp ; load & reload CCP for BOOT & WBOOT ; user defined character I/O routines extrn ?ci,?co,?cist,?cost ; each take device in extrn ?cinit ; (re)initialize device in : mvi c,20 ! jmp bdos ; read records signon$msg db 13,10,13,10,'CP/M Version 3.0, sample BIOS',13,10,0 ccp$msg db 13,10,'BIOS Err on A: No CCP.COM file',0 ccp$fcb db 1,'CCP ','COM',0,0,0,0 ds 16 fcb$nr db 0,0,0 init$table db 3 ; No external clock. ?time: ret ; CP/M BDOS Function Interfaces open: mvi c,15 ! jmp bdos ; open file control block setdma: mvi c,26 ! jmp bdos ; set data transfer address setmulti: mvi c,44 ! jmp bdos ; set record count read public ?home,?sldsk,?sttrk,?stsec,?stdma,?read,?write public ?lists,?sctrn public ?conos,?auxis,?auxos,?dvtbl,?devin,?drtbl public ?mltio,?flush,?mov,?tim,?bnksl,?stbnk,?xmov ; BIOS Jump vector. ; All BIOS routines are invoked by callir in ; to all selected devices conout: lhld @covec ; fetch console output bit vector jmp out$scan ; AUXOUT ; Auxiliary Output. Send character in ; to all selected devices auxout: lhld @aovec ; fetch aux output bit vec ; and print signon message lxi b,16*256+0 ! lxi h,@dtbl ; init all 16 logical disk drives d$init$loop: push b ; save remaining count and abs drive mov e,m ! inx h ! mov d,m ! inx h ; grab @drv entry mov a,e ! ora d ! jz d$init$next ; if null,elect disk drive, return disk parameter info ?sttrk: jmp settrk ; set disk track ?stsec: jmp setsec ; set disk sector ?stdma: jmp setdma ; set disk I/O memory address ?read: jmp read ; read physical block(s) ?write: jmp write ; write physical block(s)reset jmp vectors and exit to ccp set$jumps: if banked mvi a,1 ! call ?bnksl endif mvi a,JMP sta 0 ! sta 5 ; set up jumps in page zero lxi h,?wboot ! shld 1 ; BIOS warm start entry lhld @MXTPA ! shld 6 ; BDOS system call entry rperations. ?xmov: jmp ?xmove ; set source and destination banks for one operation jmp 0 ; reserved for future expansion jmp 0 ; reserved for future expansion jmp 0 ; reserved for future expansion ; BOOT ; Initial entry point for system ng these ; entry points. ?boot: jmp boot ; initial entry on cold start ?wboot: jmp wboot ; reentry on program exit, warm start ?const: jmp const ; return console input status ?conin: jmp conin ; return console input character ?cono: jmp conout ; get init pointer xchg ! call ipchl ; call init routine pop h ; recover @drv pointer d$init$next: pop b ; recover counter and drive # inr c ! dcr b ! jnz d$init$loop ; and loop for each drive jmp boot$1 cseg ; following in resid no drive push h ; save @drv pointer xchg ; XDPH address in dcx h ! dcx h ! mov a,m ! sta @RDRV ; get relative drive code mov a,c ! sta @ADRV ; get absolute drive code dcx h ; point to init pointer mov d,m ! dcx h ! mov e,m ?lists: jmp listst ; return list device status ?sctrn: jmp sectrn ; translate logical to physical sector ?conos: jmp conost ; return console output status ?auxis: jmp auxist ; return aux input status ?auxos: jmp auxost ; return aux output status et ds 64 boot$stack equ $ ; DEVTBL ; Return address of character device table devtbl: lxi h,@ctbl ! ret ; GETDRV ; Return address of drive table getdrv: lxi h,@dtbl ! ret ; CONOUT ; Console Output. Send charactestartup. dseg ; this part can be banked boot: lxi sp,boot$stack mvi c,15 ; initialize all 16 character devices c$init$loop: push b ! call ?cinit ! pop b dcr c ! jp c$init$loop call ?init ; perform any additional system initialization ; send console output character ?list: jmp list ; send list output character ?auxo: jmp auxout ; send auxilliary output character ?auxi: jmp auxin ; return auxilliary input character ?home: jmp home ; set disks to logical home ?sldsk: jmp seldsk ; sent memory boot$1: call set$jumps call ?ldccp ; fetch CCP for first time jmp ccp ; WBOOT ; Entry for system restarts. wboot: lxi sp,boot$stack call set$jumps ; initialize page zero call ?rlccp ; reload CCP jmp ccp ; then S maintained disk caching ?mov: jmp ?move ; block move memory to memory ?tim: jmp ?time ; Signal Time and Date operation ?bnksl: jmp bnksel ; select bank for code execution and default DMA ?stbnk: jmp setbnk ; select different bank for disk I/O DMA o ?dvtbl: jmp devtbl ; return address of device def table ?devin: jmp ?cinit ; change baud rate of device ?drtbl: jmp getdrv ; return address of disk drive table ?mltio: jmp multio ; set multiple record count for disk I/O ?flush: jmp flush ; flush BIOtor jmp out$scan ; LIST ; List Output. Send character in ; to all selected devices. list: lhld @lovec ; fetch list output bit vector out$scan: mvi b,0 ; start with device 0 co$next: dad h ; shift out next bit jnc not$out ; AUXIN ; Auxiliary Input. Return character from first ; ready auxiliary input device. auxin: lhld @aivec in$scan: push h ; save bit vector mvi b,0 ci$next: dad h ; shift out next bit mvi a,0 ; insure zero a (nonexistant dor read key if any cpi ctlq ! jnz not$q ; if its a ctl-Q, mvi a,0FFh ; set the flag ready not$q: cpi ctls ! jnz not$s ; if its a ctl-S, mvi a,00h ; clear the flag not$s: mov m,a ; save the flag call cost1 ; get the actual output status, ; all selected console output devices ; are ready. conost: lhld @covec ; get console output bit vector jmp ost$scan ; AUXOST ; Auxiliary Output Status. Return true if ; all selected auxiliary output devices ; are ready. auxostx input bit vector ist$scan: mvi b,0 ; start with device 0 cis$next: dad h ; check next bit mvi a,0 ; assume device not ready cc cist1 ; check status for this device ora a ! rnz ; if any ready, return true inr b ; drop device number ming optional ; xon/xoff support mov l,b ! mvi h,0 ; make device code 16 bits push h ; save it in stack dad h ! dad h ! dad h ; create offset into device characteristics tbl lxi d,@ctbl+6 ! dad d ; make address of mode byte mov a,m ! ani mb$x$device push h ; save the vector push b ; save the count and character not$out$ready: call coster ! ora a ! jz not$out$ready pop b ! push b ; restore and resave the character and device call ?co ; if device selected, print it pop b ; recove b ! push h call ?cost pop h ! pop b ora a ret ci1: ; get input, saving & push b ! push h call ?ci pop h ! pop b ret ; CONST ; Console Input Status. Return true if ; any selected console input device ; has an a ana m ; and mask with ctl-Q/ctl-S flag ret ; return this as the status cist1: ; get input status with and saved push b ! push h call ?cist pop h ! pop b ora a ret cost1: ; get output status, saving & push: lhld @aovec ; get aux output bit vector jmp ost$scan ; LISTST ; List Output Status. Return true if ; all selected list output devices ; are ready. listst: lhld @lovec ; get list output bit vector ost$scan: mvi b,0 ; start wiov a,h ! ora l ; see if any more selected devices jnz cis$next xra a ; all selected were not ready, return false ret ; CONIN ; Console Input. Return character from first ; ready console input device. conin: lhld @civec jmp in$scanonxoff pop h ; recover console number in jz ?cost ; not a xon device, go get output status direct lxi d,xofflist ! dad d ; make pointer to proper xon/xoff flag call cist1 ; see if this keyboard has character mov a,m ! cnz ci1 ; get flag r count and character pop h ; recover the rest of the vector not$out$device: inr b ; next device number mov a,h ! ora l ; see if any devices left jnz co$next ; and go find them... ret ; CONOST ; Console Output Status. Return true if vailable character. const: lhld @civec ; get console input bit vector jmp ist$scan ; AUXIST ; Auxiliary Input Status. Return true if ; any selected auxiliary input device ; has an available character. auxist: lhld @aivec ; get auevice ready rz ; if any not ready, return false inr b ; drop device number mov a,h ! ora l ; see if any more selected devices jnz cos$next ori 0FFh ; all selected were ready, return true ret coster: ; check for output device ready, includth device 0 cos$next: dad h ; check next bit push h ; save the vector push b ; save the count mvi a,0FFh ; assume device ready cc coster ; check status for this device pop b ; recover count pop h ; recover bit vector ora a ; see if device not ready). cc cist1 ; see if the device has a character ora a jnz ci$rdy ; this device has a character inr b ; else, next device mov a,h ! ora l ; see if any more devices jnz ci$next ; go look at them pop h ; recover bit vector jmpeter header (XDPH). read: lhld @adrv ! mvi h,0 ! dad h ; get drive code and double it lxi d,@dtbl ! dad d ; make address of table entry mov a,m ! inx h ! mov h,m ! mov l,a ; fetch table entry push h ; save address of table lxi d,-8 ! dad d> lxi h,-2 ! dad d ! mov a,m ! sta @RDRV ; get relative drive lxi h,-6 ! dad d ; find LOGIN addr mov a,m ! inx h ! mov h,m ! mov l,a ; get address of LOGIN routine call ipchl ; call LOGIN pop h ; recover DPH pointer not$first$select: inr a! dad d! jnc stoploop inx sp! inx sp! jmp pdecl stoploop: push d! push b mov c,a! call ?cono pop b! pop d nextdigit: pop h ldax b! mov e,a! inx b ldax b! mov d,a! inx b mov a,e! ora d! jnz next ret table10: dw -1000,-100,-10,ber ; in @DBNK for future disk data ; transfers. setbnk: sta @dbnk ret ; SECTRN ; Sector Translate. Indexes skew table in ; with sector in . Returns physical sector ; in . If no skew table (=0) then ; returogin procedure for drive ; if this is first select. Return ; address of disk parameter header ; in seldsk: mov a,c ! sta @adrv ; save drive select code mov l,c ! mvi h,0 ! dad h ; create index from drive code lxi b,@dtbl ! dad b in$scan ; loop til we find a character ci$rdy: pop h ; discard extra stack jmp ?ci ; Utility Subroutines ipchl: ; vectored CALL point pchl ?pmsg: ; print message @ up to a null ; saves & push b push d pmsg$ ; SETSEC ; Set Sector. Saves sector number from ; in @sect for further operations. setsec: mov l,c ! mov h,b shld @sect ret ; SETDMA ; Set Disk Memory Address. Saves DMA address ; from in @DMA and sets @DBNK to @ret ; HOME ; Home selected drive. Treated as SETTRK(0). home: lxi b,0 ; same as set track zero ; SETTRK ; Set Track. Saves track address from ; in @TRK for further operations. settrk: mov l,c ! mov h,b shld @trk ret-1,0 ?pderr: lxi h,drive$msg ! call ?pmsg ; error header lda @adrv ! adi 'A' ! mov c,a ! call ?cono ; drive code lxi h,track$msg ! call ?pmsg ; track header lhld @trk ! call ?pdec ; track number lxi h,sector$msg ! call ?pmsg ; sector ns physical=logical. sectrn: mov l,c ! mov h,b mov a,d ! ora e ! rz xchg ! dad b ! mov l,m ! mvi h,0 ret ; READ ; Read physical record from currently selected drive. ; Finds address of proper read routine from ; extended disk param ; get pointer to dispatch table mov a,m ! inx h ! mov h,m ! mov l,a ; point at disk descriptor ora h ! rz ; if no entry in table, no disk mov a,e ! ani 1 ! jnz not$first$select ; examine login bit push h ! xchg ; put pointer in stack & lxi b,table10! lxi d,-10000 next: mvi a,'0'-1 pdecl: push h!CBNK ; so that further disk operations take place ; in current bank. setdma: mov l,c ! mov h,b shld @dma lda @cbnk ; default DMA bank is current bank ; fall through to set DMA bank ; SETBNK ; Set Disk Memory Bank. Saves bank numne xofflist db -1,-1,-1,-1,-1,-1,-1,-1 ; ctl-s clears to zero db -1,-1,-1,-1,-1,-1,-1,-1 dseg ; following resides in banked memory ; Disk I/O interface routines ; SELDSK ; Select Disk Drive. Drive code in . ; Invoke lheader lhld @sect ! call ?pdec ; sector number ret ; BNKSEL ; Bank Select. Select CPU bank for further execution. bnksel: sta @cbnk ; remember current bank jmp ?bank ; and go exit through users ; physical bank select routi ; point to read routine address jmp rw$common ; use common code ; WRITE ; Write physical sector from currently selected drive. ; Finds address of proper write routine from ; extended disk parameter header (XDPH). write: lhld @adrv er input status mov a,b ! cpi 6 ! jnc null$status ; can't read from centronics mov l,b ! mvi h,0 ; make device number 16 bits lxi d,data$ports ! dad d ; make pointer to port address mov c,m ! inr c ; get SIO status port inp a ; read from work. ; baud rates 50, 75, and 110 are not supported public ?cinit,?ci,?co,?cist,?cost public @ctbl maclib Z80 ; define Z80 op codes maclib ports ; define port addresses maclib modebaud ; define mode bits and baud equates max$devichl ; leap to driver ; MULTIO ; Set multiple sector count. Saves passed count in ; @CNT multio: sta @cnt ! ret ; FLUSH ; BIOS deblocking buffer flush. Not implemented. flush: xra a ! ret ; return with no error ; errov a,m ! sta ctc$port ; get and save lxi h,serial$init$tbl jmp stream$out cent$init: lxi h,pio$init$tbl stream$out: mov a,m ! ora a ! rz mov b,a ! inx h ! mov c,m ! inx h outir jmp stream$out ?ci: ; character input mov a,b ! ! mvi h,0 ! dad h ; get drive code and double it lxi d,@dtbl ! dad d ; make address of table entry mov a,m ! inx h ! mov h,m ! mov l,a ; fetch table entry push h ; save address of table lxi d,-10 ! dad d ; point to write routine address rw$+7 ! dad d ! mov l,m ; get baud rate mov a,l ! cpi baud$600 ; see if baud > 300 mvi a,44h ! jnc hi$speed ; if >= 600, use *16 mode mvi a,0C4h ; else, use *64 mode hi$speed: sta sio$reg$4 mvi h,0 ! lxi d,speed$table ! dad d ; point to counes equ 6 cseg ?cinit: mov a,c ! cpi max$devices ! jz cent$init ; init parallel printer rnc ; invalid device mov l,c ! mvi h,0 ; make 16 bits from device number push h ; save device in stack dad h ! dad h ! dad h ; *8 lxi d,@ctblor message components drive$msg db cr,lf,bell,'BIOS Error on ',0 track$msg db ': T-',0 sector$msg db ', S-',0 ; disk communication data items @adrv ds 1 ; currently selected disk drive @rdrv ds 1 ; controller relative disk drive @trk ds cpi 6 ! jnc null$input ; can't read from centronics ci1: call ?cist ! jz ci1 ; wait for character ready dcr c ! inp a ; get data ani 7Fh ; mask parity ret null$input: mvi a,1Ah ; return a ctl-Z for no device ret ?cist: ; charact title 'Character I/O handler for z80 chip based system' ; Character I/O for the Modular CP/M 3 BIOS ; limitations: ; baud rates 19200,7200,3600,1800 and 134 ; are approximations. ; 9600 is the maximum baud rate that is likely ; tocommon: mov a,m ! inx h ! mov h,m ! mov l,a ; get address of routine pop d ; recover address of table dcx d ! dcx d ; point to relative drive ldax d ! sta @rdrv ; get relative drive code and post it inx d ! inx d ; point to DPH again pcter entry mov a,m ! sta speed ; get and save ctc count pop h ; recover lxi d,data$ports ! dad d ; point at SIO port address mov a,m ! inr a ! sta sio$port ; get and save port lxi d,baud$ports-data$ports ! dad d ; offset to baud rate port mtions end 2 ; current track number @sect ds 2 ; current sector number @dma ds 2 ; current DMA address @cnt db 0 ; record count for multisector transfer @dbnk db 0 ; bank for DMA operations cseg ; common memory @cbnk db 0 ; bank for processor operastatus port ani 1 ; isolate RxRdy rz ; return with zero ori 0FFh ret null$status: xra a ! ret ?co: ; character output mov a,b ! cpi 6 ! jz centronics$out jnc null$output mov a,c ! push psw ; save character from push b s 1 ; port address of SIO db 18h,3,0E1h,4 sio$reg$4 ds 1 db 5,0EAh db 0 ; terminator pio$init$tbl db 2,p$zpio$2b,0Fh,07h db 3,p$zpio$2a,0CFh,0F8h,07h db 0 end r output status mov a,b ! cpi 6 ! jz cent$stat jnc null$status mov l,b ! mvi h,0 lxi d,data$ports ! dad d mov c,m ! inr c inp a ; get input status ani 4 ! rz ; test transmitter empty ori 0FFh ! ret ; return true if ready cent$serial+mb$softbaud db baud$9600 db 'VAX ' ; device 5, LPT port 1 used for VAX interface db mb$in$out+mb$serial+mb$softbaud db baud$9600 db 'CEN ' ; device 6, Centronics parallel printer db mb$output db baud$none db 0 ; table terminator; save device number co$spin: call ?cost ! jz co$spin ; wait for TxEmpty pop h ! mov l,h ! mvi h,0 ; get device number in lxi d,data$ports ! dad d ; make address of port address mov c,m ; get port address pop psw ! outp a ; send data tat: in p$centstat ! cma ani 20h ! rz ori 0FFh ! ret baud$ports: ; CTC ports by physical device number db p$baud$con1,p$baud$lpt1,p$baud$con2,p$baud$con34 db p$baud$con34,p$baud$lpt2 data$ports: ; serial base ports by physical device num speed$table db 0,255,255,255,233,208,104,208,104,69,52,35,26,17,13,7 serial$init$tbl db 2 ; two bytes to CTC ctc$port ds 1 ; port address of CTC db 47h ; CTC mode byte speed ds 1 ; baud multiplier db 7 ; 7 bytes to SIO sio$port dnull$output: ret centronics$out: in p$centstat ! ani 20h ! jnz centronics$out mov a,c ! out p$centdata ; give printer data in p$centstat ! ori 1 ! out p$centstat ; set strobe ani 7Eh ! out p$centstat ; clear strobe ret ?cost: ; characte public @dtbl extrn fdsd0,fdsd1 cseg @dtbl dw fdsd0,fdsd1 dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; drives C-P non-existant end onxoff db baud$9600 db 'CRT1 ' ; device 2, CRT port 1 db mb$in$out+mb$serial+mb$softbaud db baud$9600 db 'CRT2 ' ; device 3, CRT port 2 db mb$in$out+mb$serial+mb$softbaud db baud$9600 db 'CRT3 ' ; device 4, CRT port 3 db mb$in$out+mb$sber db p$crt$data,p$lpt$data,p$con2data,p$con3data db p$con4data,p$lpt2data @ctbl db 'CRT ' ; device 0, CRT port 0 db mb$in$out+mb$serial+mb$softbaud db baud$9600 db 'LPT ' ; device 1, LPT port 0 db mb$in$out+mb$serial+mb$softbaud+mb$x title 'wd1797 w/ Z80 DMA Single density diskette handler' ; CP/M-80 Version 3 -- Modular BIOS ; Disk I/O Module for wd1797 based diskette systems ; Initial version 0.01, ; Single density floppy only. - jrp, 4 Aug 82 dseg ; mov m,a jnz new$track ; if not same track, then seek in p$fdmisc ! ani 2 ! jnz same$track ; head still loaded, we are OK new$track: ; or drive or unloaded head means we should . . . call check$seek ; . . read address and seek if wrong track entry points. ; these entries are called with the following arguments: ; relative drive number in @rdrv (8 bits) ; absolute drive number in @adrv (8 bits) ; disk transfer address in @dma (16 bits) ; disk transfer bank in @dbnk (8 birn ?conin,?cono ; con in and out extrn ?const ; get console status ; Port Address Equates maclib ports ; CP/M 3 Disk definition macros maclib cpm3 ; Z80 macro library instruction definitions maclib z80 ; common ! shld zdma$dma ; get and save DMA address lda @rdrv ! mov l,a ! mvi h,0 ; get controller-relative disk drive lxi d,select$table ! dad d ; point to select mask for drive mov a,m ! sta select$mask ; get select mask and save it out p$select ; selne by drive 0 ret init$table db 4,p$zpio$1A db 11001111b, 11000010b, 00010111b,11111111b db 4,p$zpio$1B db 11001111b, 11011101b, 00010111b,11111111b db 0 fd$login: ; This entry is called when a logical drive is about to ; be logDisk drive dispatching tables for linked BIOS public fdsd0,fdsd1 ; Variables containing parameters passed by BDOS extrn @adrv,@rdrv extrn @dma,@trk,@sect extrn @dbnk ; System Control Block variables extrn @ermde ; BDOS error d$msg ; point at " Read " mvi a,88h ! mvi b,01h ; 1797 read + Z80DMA direction jmp rw$common fd$write: lxi h,write$msg ; point at " Write " mvi a,0A8h ! mvi b,05h ; 1797 write + Z80DMA direction ; jmp wr$common rw$common: ; seek to cts) ; disk track address in @trk (16 bits) ; disk sector address in @sect (16 bits) ; pointer to XDPH in ; they transfer the appropriate data, perform retries ; if necessary, then return an error code in fd$read: lxi h,reacontrol characters cr equ 13 lf equ 10 bell equ 7 ; Extended Disk Parameter Headers (XPDHs) dw fd$write dw fd$read dw fd$login dw fd$init0 db 0,0 ; relative drive zero fdsd0 dph trans,dpbsd,16,31 dw fd$write dw fd$readect drive more$retries: mvi c,10 ; allow 10 retries retry$operation: push b ; save retry counter lda select$mask ! lxi h,old$select ! cmp m mov m,a jnz new$track ; if not same drive as last, seek lda @trk ! lxi h,old$track ! cmp m ged into for the purpose of density determination. ; It may adjust the parameters contained in the disk ; parameter header pointed at by ret ; we have nothing to do in ; simple single density only environment. ; disk READ and WRITEmode ; Utility routines in standard BIOS extrn ?wboot ; warm boot vector extrn ?pmsg ; print message @ up to 00, saves & extrn ?pdec ; print binary number in from 0 to 99. extrn ?pderr ; print BIOS disk error header extorrect track (if necessary), ; initialize DMA controller, ; and issue 1797 command. shld operation$name ; save message for errors sta disk$command ; save 1797 command mov a,b ! sta zdma$direction ; save Z80DMA direction code lhld @dmaterface ; Initialization entry point. ; called for first time initialization. fd$init0: lxi h,init$table fd$init$next: mov a,m ! ora a ! rz mov b,a ! inx h ! mov c,m ! inx h outir jmp fd$init$next fd$init1: ; all initialization do dw fd$login dw fd$init1 db 1,0 ; relative drive one fdsd1 dph trans,dpbsd,16,31 cseg ; DPB must be resident dpbsd dpb 128,26,77,1024,64,2 dseg ; rest is banked trans skew 26,6,1 ; Disk I/O routines for standardized BIOS in lxi b,16667 ; 100 ms / (24 t states*250 ns) spin$loop: ; wait for head/seek settling dcx b mov a,b ! ora c jnz spin$loop same$track: lda @trk ! out p$fdtrack ; give 1797 track lda @sect ! out p$fdsector ; and sector lxi h,dma$blocll ?cono pop psw ! cpi 'a' ! rc sui 'a'-'A' ; make upper case ret disk$command ds 1 ; current wd1797 command select$mask ds 1 ; current drive select code old$select ds 1 ; last drive selected old$track ds 1 ; last track seeked to disk$sta ; try to read ID, put track in jz id$ok ; if OK, we're OK call step$out ; else step towards Trk 0 call read$id ; and try again jz id$ok ; if OK, we're OK call restore ; else, restore the drive mvi b,0 ; and make like we are ad status sta disk$status ; save status for error messages pop b ; recover retry counter ora a ! rz ; check status and return to BDOS if no error ani 0001$0000b ; see if record not found error cnz check$seek ; if a record not found, we mDDRESS operation outir mvi a,11000100b ; issue 1797 read address command call exec$command ; wait for IREQ and read status ani 10011101b ; mask status lxi h,id$buffer ! mov b,m ; get actual track number in ret ; and return with Z flag tany more bits left, continue lxi h,error$msg ! call ?pmsg ; print ", Retry (Y/N) ? " call u$conin$echo ; get operator response cpi 'Y' ! jz more$retries ; Yes, then retry 10 more times hard$error: ; otherwise, mvi a,1 ! ret ; return hark ; point to dma command block lxi b,dmab$length*256 + p$zdma ; command block length and port address outir ; send commands to Z80 DMA in p$bankselect ; get old value of bank select port ani 3Fh ! mov b,a ; mask off DMA bank and save ldmmand step$out: mvi a,01101010b ; step out once at 10 ms. jmp exec$command restore: mvi a,00001011b ; restore at 15 ms ; jmp exec$command exec$command: ; issue 1797 command, and wait for IREQ ; return status out p$fdct track 0 id$ok: mov a,b ! out p$fdtrack ; send current track to track port lda @trk ! cmp b ! pop b ! rz ; if its desired track, we are done out p$fddata ; else, desired track to data port mvi a,00011010b ; seek w/ 10 ms. steps jmp exec$coight need to seek dcr c ! jnz retry$operation ; suppress error message if BDOS is returning errors to application... lda @ermde ! cpi 0FFh ! jz hard$error ; Had permanent error, print message like: ; BIOS Err on d: T-nn, S-mm, , Retry ? call ?pderr ; print message header lhld operation$name ! call ?pmsg ; last function ; then, messages for all indicated error bits lda disk$status ; get status byte from last error lxi h,error$table ; point attus ds 1 ; last error status code for messages select$table db 0001$0000b,0010$0000b ; for now use drives C and D ; error message components read$msg db ', Read',0 write$msg db ', Write',0 operation$name dw read$msg ; table of pointers k db 0C3h ; reset DMA channel db 14h ; channel A is incrementing memory db 28h ; channel B is fixed port address db 8Ah ; RDY is high, CE/ only, stop on EOB db 79h ; program all of ch. A, xfer B->A (temp) zdma$dma ds 2 ; starting DMA address r ; use Z80 block move instruction xchg ; need next addresses in same regs ret ; by exiting through bank select ?bank: push b ; save register b for temp ral ! ral ! ral ! ani 18h ; isolate bank in proper bit position mov b,a ; sa port address (1797 data port) db 0CFh ; load dest (currently source) register db 01h ; xfer B->A db 0CFh ; load source register db 87h ; enable DMA channel length$id$dmab equ $-read$id$block cseg ; easier to put ID buffer in common id$to error message strings ; first entry is for bit 7 of 1797 status byte error$table dw b7$msg dw b6$msg dw b5$msg dw b4$msg dw b3$msg dw b2$msg dw b1$msg dw b0$msg b7$msg db ' Not ready,',0 b6$msg db ' Protect,',0 b5$msg d dw 128-1 ; 128 byte sectors in SD db 85h ; xfer byte at a time, ch B is 8 bit address db p$fddata ; ch B port address (1797 data port) db 0CFh ; load B as source register db 05h ; xfer A->B db 0CFh ; load A as source register zdma$directive in reg B in p$bankselect ; get old memory control byte ani 0E7h ! ora b ; mask out old and merge in new out p$bankselect ; put new memory control byte pop b ; restore register b ret ; 128 bytes at a time end buffer ds 6 ; buffer to hold ID field ; track ; side ; sector ; length ; CRC 1 ; CRC 2 end  register db 87h ; enable DMA channel length$id$dmab equ $-read$id$block cseg ; easier to put ID buffer in common id$b ' Fault,',0 b4$msg db ' Record not found,',0 b3$msg db ' CRC,',0 b2$msg db ' Lost data,',0 b1$msg db ' DREQ,',0 b0$msg db ' Busy,',0 error$msg db ' Retry (Y/N) ? ',0 ; command string for Z80DMA device for normal operation dma$bloc title 'bank & move module for CP/M3 linked BIOS' cseg public ?move,?xmove,?bank extrn @cbnk maclib z80 maclib ports ?xmove: ; ALTOS can't perform interbank moves ret ?move: xchg ; we are passed source in DE and dest in HL ldiort address db 8Ah ; RDY is high, CE/ only, stop on EOB db 7Dh ; program all of ch. A, xfer A->B (temp) dw id$buffer ; starting DMA address dw 6-1 ; Read ID always xfers 6 bytes db 85h ; byte xfer, ch B is 8 bit address db p$fddata ; ch Bon ds 1 ; either A->B or B->A db 0CFh ; load final source register db 87h ; enable DMA channel dmab$length equ $-dma$block read$id$block db 0C3h ; reset DMA channel db 14h ; channel A is incrementing memory db 28h ; channel B is fixed p title 'System Control Block Definition for CP/M3 BIOS' public @civec, @covec, @aivec, @aovec, @lovec, @bnkbf public @crdma, @crdsk, @vinfo, @resel, @fx, @usrcd public @mltio, @ermde, @erdsk, @media, @bflgs public @date, @hour, @min, @secD = N ALTBNKSE = N ALTBNKSF = N ALTBNKSG = N ALTBNKSH = N ALTBNKSI = N ALTBNKSJ = N ALTBNKSK = N ALTBNKSL = N ALTBNKSM = N ALTBNKSN = N ALTBNKSO = N ALTBNKSP = N NDIRRECA = 01 NDIRRECB = 01 NDIRRECC = 01 NDIRRECD = 01 NDIRRECE = 01 NDIRREse+62h ; Top of User TPA ; (address at 6,7)(word, r/o) end  ; Vector (word, r/w) @LOVEC equ scb$base+2Ah ; List Output Redirection ; Vector (word, r/w) @BNKBF equ scb$base+35h ; Address of 128 Byte Buffer ; for Banked B,C0,05 MEMSEG05 = 00,C0,06 MEMSEG06 = 00,C0,07 MEMSEG07 = 00,C0,08 MEMSEG08 = 00,C0,09 MEMSEG09 = 00,C0,0A MEMSEG0A = 00,C0,0B MEMSEG0B = 00,C0,0C MEMSEG0C = 00,C0,0D MEMSEG0D = 00,C0,0E MEMSEG0E = 00,C0,0F MEMSEG0F = 00,C0,10 HASHDRVA = N HASpen door (byte,r/w) @BFLGS equ scb$base+57h ; BDOS Message Size Flag (byte,r/o) @DATE equ scb$base+58h ; Date in Days Since 1 Jan 78 ; (word, r/w) @HOUR equ scb$base+5Ah ; Hour in BCD (byte, , ?erjmp, @mxtpa scb$base equ 0FE00H ; Base of the SCB @CIVEC equ scb$base+22h ; Console Input Redirection ; Vector (word, r/w) @COVEC equ scb$base+24h ; Console Output Redirection IOS (word, r/o) @CRDMA equ scb$base+3Ch ; Current DMA Address ; (word, r/o) @CRDSK equ scb$base+3Eh ; Current Disk (byte, r/o) @VINFO equ scb$base+3Fh ; BDOS Variable "INFO" HDRVB = N HASHDRVC = N HASHDRVD = N HASHDRVE = Y HASHDRVF = Y HASHDRVG = Y HASHDRVH = Y HASHDRVI = Y HASHDRVJ = Y HASHDRVK = Y HASHDRVL = Y HASHDRVM = Y HASHDRVN = Y HASHDRVO = Y HASHDRVP = Y ALTBNKSA = N ALTBNKSB = N ALTBNKSC = N ALTBNKSr/w) @MIN equ scb$base+5Bh ; Minute in BCD (byte, r/w) @SEC equ scb$base+5Ch ; Second in BCD (byte, r/w) ?ERJMP equ scb$base+5Fh ; BDOS Error Message Jump ; (word, r/w) @MXTPA equ scb$ba ; Vector (word, r/w) @AIVEC equ scb$base+26h ; Auxiliary Input Redirection ; Vector (word, r/w) @AOVEC equ scb$base+28h ; Auxiliary Output Redirection PRTMSG = N PAGWID = 4F PAGLEN = 17 BACKSPC = N RUBOUT = N BOOTDRV = A MEMTOP = FF BNKSWT = Y COMBAS = 60 LERROR = Y NUMSEGS = 01 MEMSEG00 = 10,1A,00 MEMSEG01 = 00,C0,02 MEMSEG02 = 00,C0,03 MEMSEG03 = 00,C0,04 MEMSEG04 = 00e, r/o) @MLTIO equ scb$base+4Ah ; Current Multi-Sector Count ; (byte,r/w) @ERMDE equ scb$base+4Bh ; BDOS Error Mode (byte, r/o) @ERDSK equ scb$base+51h ; BDOS Error Disk (byte,r/o) @MEDIA equ scb$base+54h ; Set by BIOS to indicate ; o ; (word, r/o) @RESEL equ scb$base+41h ; FCB Flag (byte, r/o) @FX equ scb$base+43h ; BDOS Function for Error ; Messages (byte, r/o) @USRCD equ scb$base+44h ; Current User Code (bytCF = 01 NDIRRECG = 01 NDIRRECH = 01 NDIRRECI = 01 NDIRRECJ = 01 NDIRRECK = 01 NDIRRECL = 01 NDIRRECM = 01 NDIRRECN = 01 NDIRRECO = 01 NDIRRECP = 01 NDTARECA = 01 NDTARECB = 01 NDTARECC = 01 NDTARECD = 01 NDTARECE = 01 NDTARECF = 01 NDTARECud$4800 equ 12 ; 4800 baud baud$7200 equ 13 ; 7200 baud baud$9600 equ 14 ; 9600 baud baud$19200 equ 15 ; 19.2k baud -1 ZCMOVE EQU * LDA ZCODELEN*CPMCARD+ZCODE,Y STA 0-ZOFFSET+$9000,Y DEY BPL ZCMOVE * * SETUP BOOT SLOT FOR Z80'S EDIFICATION: * LDA $2B STA BOOTSLOT ;SQUIRREL IT AWAY * * SET CURTRK SO THE Z80'S CORE ROUTINES ARE HAPPY: * LSR A ;MAKE 0N LSR A LSR RVK = A ODTADRVL = A ODTADRVM = A ODTADRVN = A ODTADRVO = A ODTADRVP = A OVLYDIRA = Y OVLYDIRB = N OVLYDIRC = Y OVLYDIRD = Y OVLYDIRE = Y OVLYDIRF = Y OVLYDIRG = Y OVLYDIRH = Y OVLYDIRI = Y OVLYDIRJ = Y OVLYDIRK = Y OVLYDIRL = Y OVLYDIRM equ 0000$1000b ; device may use protocol mb$xon$xoff equ 0001$0000b ; XON/XOFF protocol ; enabled baud$none equ 0 ; no baud rate associated ; with this device baud$50 equ 1 ; 50 baud baud$75 equ 2 ; 75 baud baud$110 equ 3 ; tem tracks db ?psh,?psm ; physical sector size shift ; and mask endm ; gcd macro ?m,?n ;; greatest common divisor of m,n ;; produces value gcdn as result ;; (used in sector translate table generation) ?gcdm set ?m ;G = 01 NDTARECH = 01 NDTARECI = 01 NDTARECJ = 01 NDTARECK = 01 NDTARECL = 01 NDTARECM = 01 NDTARECN = 01 NDTARECO = 01 NDTARECP = 01 ODIRDRVA = A ODIRDRVB = A ODIRDRVC = A ODIRDRVD = A ODIRDRVE = A ODIRDRVF = A ODIRDRVG = A ODIRDRVH = A ORECT INSTRUCTION. THE FALSE-READ * MIGHT CAUSE PROBLEMS WITH THE Z80, SO WE'LL AVOID IT... * AWESOME EQU * ;JUST LIKE Z'S ON THE ROAD LDA #00 ;Z80 NOP (IT GETS EXECUTED AS LOC 0000) STORE STA $C700 ;SCAN DOWNWARD * * WE CONTINUE EXECUTION HERE FOR ONE A LSR A TAY LDA $44 ;GET THE HALFTRACK STA $0478,Y ;DRIVE #1 IS THERE LDA #0 STA $04F8,Y ;DRIVE #2 ASSUMED ON ZERO * * SCAN FOR A Z80 CARD, STARTING AT SLOT 7. * * NOTE: THIS IS SELF-MODIFYING CODE TO AVOID THE FALSE-READ * WHICH OCCURS ON AN INDI= Y OVLYDIRN = Y OVLYDIRO = Y OVLYDIRP = Y OVLYDTAA = Y OVLYDTAB = N OVLYDTAC = Y OVLYDTAD = Y OVLYDTAE = Y OVLYDTAF = Y OVLYDTAG = Y OVLYDTAH = Y OVLYDTAI = Y OVLYDTAJ = Y OVLYDTAK = Y OVLYDTAL = Y OVLYDTAM = Y OVLYDTAN = Y OVLYDTAO = Y 110 baud baud$134 equ 4 ; 134.5 baud baud$150 equ 5 ; 150 baud baud$300 equ 6 ; 300 baud baud$600 equ 7 ; 600 baud baud$1200 equ 8 ; 1200 baud baud$1800 equ 9 ; 1800 baud baud$2400 equ 10 ; 2400 baud baud$3600 equ 11 ; 3600 baud ba SBTL 'Z80 Setup Routines' CHR '-' CrankZ80 EQU * DO CPMCARD * * MOVE THE 6502/Z80 LINKAGE DOWN TO $0300: * LDY #0 MoveIt EQU * LDA $0B00,Y STA $0300,Y INY BNE MoveIt FIN * * Setup the 'unhappy' Z80 code: * ZOFFSET EQU CPMCARD*$8000 LDY #ZCODELENDIRDRVI = A ODIRDRVJ = A ODIRDRVK = A ODIRDRVL = A ODIRDRVM = A ODIRDRVN = A ODIRDRVO = A ODIRDRVP = A ODTADRVA = A ODTADRVB = A ODTADRVC = A ODTADRVD = A ODTADRVE = A ODTADRVF = A ODTADRVG = A ODTADRVH = A ODTADRVI = A ODTADRVJ = A ODTAD ; equates for mode byte bit fields mb$input equ 0000$0001b ; device may do input mb$output equ 0000$0010b ; device may do output mb$in$out equ mb$input+mb$output mb$soft$baud equ 0000$0100b ; software selectable ; baud rates mb$serialecords per track db ?bsh,?blm ; block shift and mask db ?exm ; extent mask dw ?dsm ; maximum block number dw ?drm ; maximum directory entry number db ?al0,?al1 ; alloc vector for directory dw ?cks ; checksum size dw ?off ; offset for sys OVLYDTAP = Y CRDATAF = N DBLALV = Y y typing SUBMI MAKBOOT FILENAME.EX (wher filename.ex i th fil generated above.) ; I/O Port addresses for Z80 chip set ; based system with wd1797 FDC ; chip bases p$zdma equ 0 p$wd1797 equ 4 p$zpio1 equ 8 p$zctc1 equ 12 p$zpio2 equ 16 p$boot equ 20 ; OUT disables boot EPROM p$zdart equ 28 ; console 1 and printard types: REP 40 SlotScan EQU * LDA #>IoTable LDY #scan them slots... REP 40 * Initialize the I/O Cards: REP 40 LDA #7 ;do slots 7..1 STA SlotCntr * LDA #$4C ;setup JUMP instr STA InitJump LDANHAPPY EQU * DEC Z80SLOT ;(PASSED TO Z80) DEC STORE+2 ;BUMP SLOT LDA STORE+2 CMP #$C1 ;ALL DONE WITH SLOTS? BCS AWESOME ;->KEEP TRYING * * NO CARD. COMPLAIN... * LDX #0 ;INDEX PRINT EQU * LDA MESSAGE,X JSR COUT INX CPX #MSGLEN BCC PRINT JMP $F, Centronics printer interface p$cent$stat equ p$zpio2+0 p$cent$data equ p$zpio2+1 p$zpio2a equ p$zpio2+2 p$zpio2b equ p$zpio2+3 ; dual asynch rcvr/xmtr, console and serial printer ports p$crt$data equ p$zdart+0 p$crt$stat equ p$zdart+1 p$M R.Boot EQU 2 ;Bootable device R.Firm EQU 3 ;Firmware protocol R.Serial EQU 4 ;Serial card protocol R.Other EQU 5 ;Other: try BASIC protocol * InsDs2 EQU $F88E ;disassembler * * Zeropage usage: * DSECT ORG $3C SlotPtr DS 2 ;for accessing slot roms SlotPer 1 p$zpio3 equ 36 p$zsio1 equ 40 p$zsio2 equ 44 p$zctc2 equ 48 ; diskette controller chip ports p$fdcmnd equ p$wd1797+0 p$fdstat equ p$wd1797+0 p$fdtrack equ p$wd1797+1 p$fdsector equ p$wd1797+2 p$fddata equ p$wd1797+3 ; parallel 1-7 * in an Apple ][ or //e. The cards are classified into * six (6) types: * * - Empty (no Cn00 ROM) * - Invalid (Cn00 ROM but not valid) * - Bootable device * - Firmware Protocol * - Serial Card Protocol * - Other F65 ;OFF TO THE MONITOR * DO CPMCARD MESSAGE ASC '** NO CP/M CARD IN SYSTEM **' ELSE MESSAGE ASC '** NO Z-CARD IN SYSTEM **' FIN MSGLEN EQU *-MESSAGE SBTL 'I/O Card Identify/Initialize' REP 40 * * SlotFinder: This program will identify cards in slotslpt$data equ p$zdart+2 p$lpt$stat equ p$zdart+3 ; Third Parallel I/O device p$configuration equ p$zpio3+0 p$bankselect equ p$zpio3+1 p$zpio3a equ p$zpio3+2 p$zpio3b equ p$zpio3+3 ; Serial I/O device 1, printer 2 and console 4 p$lpt2datrL EQU SlotPtr SlotPtrH EQU SlotPtr+1 InfoPtr DS 2 ;for returned slot info InfoPtrL EQU InfoPtr InfoPtrH EQU InfoPtr+1 SumValue DS 1 ;for CheckRom SlotCntr DS 1 SlotN0 DS 1 InitJump DS 3 ;will be JMP-->CnXX DEND * PAGE REP 40 * Scan the I/O slots for cOF THREE REASONS: * 1. THE Z80 DIDN'T START UP; * 2. THE Z80 ISN'T HAPPY (E.G. WRONG Z80 CARD); * 3. THE Z80 IS HAPPY: WE SHOULD JUMP TO $0303. * LDA Z80HAPPY ;IS IT A HAPPY Z80? BEQ UNHAPPY ;->NOPE JMP SLOTSCAN ;->YES, NOW CHECK OUT I/O * U I/O 1 p$select equ p$zpio1+0 p$fdint equ p$zpio1+0 p$fdmisc equ p$zpio1+1 p$zpio1a equ p$zpio1+2 p$zpio1b equ p$zpio1+3 ; counter timer chip 1 p$baudcon1 equ p$zctc1+0 p$baudlpt1 equ p$zctc1+2 p$index equ p$zctc1+3 ; parallel I/O 2(try BASIC protocol) * * Entry points are as follows: * * ChkSlot: Given slot# in AC, returns type in AC. * ChkAll : Given ADH in Y, ADL in AC, returns info (AC&Y). * REP 40 * R.Empty EQU 0 ;Empty slot (no Cn00 ROM) R.Invalid EQU 1 ;Invalid Cn00 ROcond Counter Timer Circuit p$baudcon2 equ p$zctc2+0 p$baudcon34 equ p$zctc2+1 p$baudlpt2 equ p$zctc2+2 p$rtc equ p$zctc2+3 ta equ p$zsio1+0 p$lpt2stat equ p$zsio1+1 p$con4data equ p$zsio1+2 p$con4stat equ p$zsio1+3 ; Serial I/O device 2, console 2 and 3 p$con2data equ p$zsio2+0 p$con2stat equ p$zsio2+1 p$con3data equ p$zsio2+2 p$con3stat equ p$zsio2+3 ; se #$C7 ;start up at seven STA SlotPtrH STA InitJump+2 LDA #0 STA SlotPtrL * * Setup the pointers and things: * InitSlot EQU * LDA SlotPtrH ;construct n0 ASL A ASL A ASL A ASL A STA SlotN0 ; LDA $CFFF ;turn off expansion ROMs LDY #$0D ;offset to erial card LDA #R.Serial ;it really is a serial card JMP ChkExit * * If it isn't SERIAL or FIRMWARE, it's OTHER or INVALID: * NotSerial EQU * LDY #0 LDA (SlotPtr),Y ;get opcode at Cn00 JSR InsDs2 ;disassemble it TAY ;move the mnemonic-index LDA #R.yte CMP DiskId,Y ;check it BNE NotBoot ;->not bootable DEY DEY BPL ChkBoot ;do all four bytes LDA #R.Boot ;it's a bootable device JMP ChkExit * * It's not a bootable device. Does it look like a Serial Card? * NotBoot EQU * LDY #5 ;check Cn05 for SEN0 ;setup Y STY $6F8 ;NEEDED BY OLD VIDEX PROMS JSR $C800 ;init the card * InitNext EQU * DEC SlotPtrH ;bump down a slot DEC InitJump+2 DEC SlotCntr BNE InitSlot REP 40 * We're done with the startup stuff. Go back to * where the Z80 wants us to go:it's OTHER LDA $C800 ;get first byte (Init entry) JSR InsDs2 ;disassemble it CMP #$10 ;invalid opcode? BEQ NotSerial ;->not a good serial card LDA $C84D ;get the "input" routine JSR InsDs2 ;disassemble it CMP #$10 ;invalid opcode? BEQ NotSerial ;-> STA SlotPtrL ;make it Cn00 * TYA ;save PHA ; Y * * Check for a Cn00 ROM. If none, then it's EMPTY. * JSR CheckROM ;check for ROM BCC NotEmpty ;=>there's some ROM there LDA #R.Empty ;"empty" JMP ChkExit ;->all done * * OK, so there's a Cn00 ROM. Is INIT byte LDA (SlotPtr),Y ;get init offset STA InitJump+1 ; (assuming Firmware card) * * What kind of card? * LDY SlotCntr LDA (InfoPtr),Y ;get card type CMP #R.Firm ;firmware card? BNE InitSer ;->no. maybe serial * * Initialize a firmware card: * Could it be a Firmware card? * LDY #$0B ;look for Generic Signature byte LDA (SlotPtr),Y CMP #$01 ;is it a firmware card? BNE SerialC8 ;->regular serial. Validate C8 space. LDA #R.Firm ;say what it is JMP ChkExit * * If it's to be a REAL serial cardC LDA (SlotPtr),Y ;get the byte CMP #$38 ;is it an SEC? BNE NotSerial ;->nope, not serial nor firmware LDY #7 ;check Cn07 for CLC LDA (SlotPtr),Y CMP #$18 ;is it a CLC? BNE NotSerial ;->no, can't be a Serial card * * It appears to be a serial card. REP 40 JMP $0303 PAGE REP 40 * Name : ChkAll * Function: Get info for all 7 I/O slots * Input : AC=Lo address for 8-byte info returned * : Y=Hi address * Output : The info * Volatile: none REP 40 * ChkAll EQU * STA InfoPtrL ;setup poinot a good serial card * INC SlotPtrH ;bump pointer to C9xx JSR CheckROM ;check for ROM BCS NotSerial ;->if no C9, then it's OTHER LDA $C9AA ;get the "output" routine JSR InsDs2 ;disassemble it CMP #$10 ;invalid opcode? BEQ NotSerial ;->not a good sit a bootable device? * NotEmpty EQU * LDY #0 LDA (SlotPtr),Y ;get opcode at Cn00 JSR InsDs2 ;disassemble it CMP #$10 ;invalid opcode? BEQ NotBoot ;->invalid; can't boot it * LDY #7 ;check even bytes 00..07 ChkBoot EQU * LDA (SlotPtr),Y ;get a bLDX SlotPtrH ;setup X LDY SlotN0 ;setup Y JSR InitJump ;go init the card JMP InitNext * * If it's a Serial card, initialize it: * InitSer EQU * CMP #R.Serial ;is it serial? BNE InitNext ;->nope, forget initialization * LDX SlotPtrH ;setup X LDY Slot, there had better be some * ROM in the C8 space. * SerialC8 EQU * LDA $CFFF ;turn other C8 ROMs off LDA (SlotPtr),Y ;any Cn turns ours on * LDA #$C8 ;set pointer to C8space STA SlotPtrH * JSR CheckROM ;check for ROM BCS NotSerial ;->if no C8, then oPtrL ;restore AC LDY InfoPtrH ; and Y RTS PAGE REP 40 * Name : ChkSlot * Function: Get info for given I/O Slot * Input : AC=slot number 1..7 * Output : AC=Info * Volatile: none REP 40 * ChkSlot EQU * ORA #$C0 ;compute Cn STA SlotPtrH LDA #0 nter STY InfoPtrH ; to returned info * * Get info on all 7 slots: * LDY #7 ;start at the top ChkAll2 EQU * TYA ;slot-->AC JSR ChkSlot ;get me the info, pal STA (InfoPtr),Y ;return the info DEY ;do next lower slot BNE ChkAll2 ;->more to go * LDA Inf ; CALLVERS program bdos equ 5 ; entry point for BDOS prtstr equ 9 ; print string function vers equ 12 ; get version function cr equ 0dh ; carriage return lf equ 0ah ; line feed org 100h mvi d,5 ; Perform 5 times loop: push d ;uffer function call bdos ret ; ; gnb: ;get next byte lda ibp cpi 80h jnz g0 ; read another buffer ; ; call diskr ora a ;zero value if read ok jz g0 ;for another byte ; end of data, return with carry set for eof stc ret ; g0: ;rnter to 80h ; hl contains next address to print lxi h,0 ;start with 0000 ; gloop: push h ;save line position call gnb pop h ;recall line position jc finis ;carry set by gnb if end file mov b,a ; print hex values ; check for line fold movop b! pop d! pop h; restored ret ; crlf: mvi a,cr call pchar mvi a,lf call pchar ret ; ; pnib: ;print nibble in reg a ani 0fh ;low 4 bits cpi 10 jnc p10 ; less than or equal to 9 adi '0' jmp prn ; ; greater or equal to 10 p10qu fcb+33 ;fcb length ; ; set up stack lxi h,0 dad sp ; entry stack pointer in hl from the ccp shld oldsp ; set sp to local stack area (restored at finis) lxi sp,stktop ; read and print successive buffers call setup ;set up input file cpi save counter mvi c,prtstr lxi d,call$msg ; print call message call bdos mvi c,vers call bdos ; try to get version # ; CALLVERS will intercept mov a,l sta curvers pop d dcr d ; decrement counter jnz loop mvi c,um: inx h ;to next line number mvi a,' ' call pchar mov a,b call phex jmp gloop ; finis: ; end of dump call crlf lhld oldsp sphl ; stack pointer contains ccp's stack location ret ;to the ccp ; ; ; subroutines ; break: ;check b a,l ani 0fh ;check low 4 bits jnz nonum ; print line number call crlf ; ; check for break key call break ; accum lsb = 1 if character ready rrc ;into carry jc finis ;don't print any more ; mov a,h call phex mov a,l call phex non; Dump program, reads input file and displays hex data ; org 100h bdos equ 0005h ;dos entry point cons equ 1 ;read console typef equ 2 ;type function printf equ 9 ;buffer print entry brkf equ 11 ;break key function (true if char ready) openf equ 1: adi 'a' - 10 prn: call pchar ret ; phex: ;print hex char in reg a push psw rrc rrc rrc rrc call pnib ;print nibble pop psw call pnib ret ; err: ;print error message ; d,e addresses message ending with "$" mvi c,printf ;print b255 ;255 if file not present jnz openok ;skip if open is ok ; ; file not there, give error message and return lxi d,opnmsg call err jmp finis ;to return ; openok: ;open operation ok, set buffer index to end mvi a,80h sta ibp ;set buffer poi0 jmp bdos call$msg: db cr,lf,'**** CALLVERS **** $' curvers db 0 end reak key (actually any key will do) push h! push d! push b; environment saved mvi c,brkf call bdos pop b! pop d! pop h; environment restored ret ; pchar: ;print a character push h! push d! push b; saved mvi c,typef mov e,a call bdos pfcb+0 ;disk name fcbfn equ fcb+1 ;file name fcbft equ fcb+9 ;disk file type (3 characters) fcbrl equ fcb+12 ;file's current reel number fcbrc equ fcb+15 ;file's record count (0 to 128) fcbcr equ fcb+32 ;current (next) record number (0 to 127) fcbln e5 ;file open readf equ 20 ;read function ; fcb equ 5ch ;file control block address buff equ 80h ;input disk buffer address ; ; non graphic characters cr equ 0dh ;carriage return lf equ 0ah ;line feed ; ; file control block definitions fcbdn equ ead the byte at buff+reg a mov e,a ;ls byte of buffer index mvi d,0 ;double precision index to de inr a ;index=index+1 sta ibp ;back to memory ; pointer is incremented ; save the current file address lxi h,buff dad d ; absolute character addversion for random access mvi c,openf ;open default fcb rdname: lda fcb+1 cpi ' ' jnz opfile lxi d,entmsg call print call parse jmp versok opfile: lxi d,fcb call bdos inr a ;err 255 becomes zero ************ org 100h ;base of tpa ; reboot equ 0000h ;system reboot bdos equ 0005h ;bdos entry point ; coninp equ 1 ;console input function conout equ 2 ;console output function pstring equ ; variable area ibp: ds 2 ;input buffer pointer oldsp: ds 2 ;entry sp value from ccp ; ; stack area ds 64 ;reserve 32 level stack stktop: ; end  * ;* load SP, set-up file for random access * ;* * ;*************************************************** lxi sp,stack ; ; version 3.1? mt test$msg: db cr,lf,'**** ECHOVERS **** $' ret$stack: dw 0 ds 32 ; 16 level stack loc$stack: end ress is in hl mov a,m ; byte is in the accumulator ora a ;reset carry bit ret ; setup: ;set up file ; open the file for input xra a ;zero to accum sta fcbcr ;clear current record ; lxi d,fcb mvi c,openf call bdos ; 255 in accum if op readr equ 33 ;read random writer equ 34 ;write random wrtrzf equ 40 ;write random zero fill parsef equ 152 ;parse function ; fcb equ 005ch ;default file control block ranrec equ fcb+33 ;random record positi9 ;print string until '$' rstring equ 10 ;read console buffer version equ 12 ;return version number openf equ 15 ;file open function closef equ 16 ;close function makef equ 22 ;make file function ; ECHOVERS RSX pstring equ 9 ; string print function cr equ 0dh lf equ 0ah ; ; RSX PREFIX STRUCTURE ; db 0,0,0,0,0,0 ; room for serial number jmp ftest ; begin of program next db 0c3H ; jump dw 0 ; next module in line prevvi c,version call bdos cpi 31h ;version 3.1 or better? jnc versok ; bad version, message and go back lxi d,badver call print jmp reboot ; versok: ; correct ;*************************************************** ;* * ;* sample random access program for cp/m 3 * ;* * ;***************************************en error ret ; diskr: ;read disk file record push h! push d! push b lxi d,fcb mvi c,readf call bdos pop b! pop d! pop h ret ; ; fixed message area signon: db 'file dump version 2.0$' opnmsg: db cr,lf,'no input file present on disk$' on ranovf equ fcb+35 ;high order (overflow) byte buff equ 0080h ;buffer address ; cr equ 0dh ;carriage return lf equ 0ah ;line feed ; ;*************************************************** ;* i h,0 dad sp ;save stack shld ret$stack lxi sp,loc$stack mvi c,pstring lxi d,test$msg ; print message call next ; call BDOS lhld ret$stack ; restore user stack sphl lxi h,0031h ; return version number = 0031h re: dw 0 ; previous module remov: db 0ffh ; remove flag set nonbnk: db 0 db 'ECHOVERS' space: ds 3 ftest: ; is this function 12? mov a,c cpi 12 jz begin ; yes - intercept jmp next ; some other function begin: lx jnz ready ; ; cannot open file, so create it mvi c,makef lxi d,fcb call bdos inr a ;err 255 becomes zero jnz ready ; ; cannot create file, directory full zero? jnz error ;message if not jmp ready ;for another record ; ;*************************************************** ;* * ;* end of write commands, process read r mvi c,writer lxi d,fcb call bdos ora a ;error code zero? jnz error ;message if not jmp ready ;for another record ; ; ;********************************************** h,ranovf mov m,c ;set ranrec high byte cpi 'Q' ;quit? jnz notq ; ; quit processing, close file mvi c,closef lxi d,fcb call bdos inr a ;err 255 pop b ;restore next to fill cpi cr ;end of line? jz erloop1 ; not end, store character mov m,a inx h ;next to fill dcr c ;counter goes down jnz ;next destination call getchr ;character to a pop h ;restore counter pop b ;restore next to fill cpi cr ;end of line? jz erloop ; not end, store character lxi d,nospace call print jmp reboot ;back to ccp ; ;*************************************************** ;* * ;* loop back to "ready" after each command * ;* not the quit command, random write zero fill? cpi 'F' jnz notf ; ; this is a random write, fill buffer until cr lxi d,datmsg call print ;data prompt mvi c,127 ;up to 127 cha********** ;* * ;* end of write command, process write random zero fill * ;* * ;******************************************************** notw: ;becomes 0 jz error ;error message, retry jmp reboot ;back to ccp ; ;*************************************************** ;* * ;* end of quit command, process write rloop1 ;end of buffer? erloop1: ; end of read loop, store 00 mvi m,0 ; ; write the record to selected record number mvi c,wrtrzf lxi d,fcb call bdos ora a ;error code mov m,a inx h ;next to fill dcr c ;counter goes down jnz rloop ;end of buffer? erloop: ; end of read loop, store 00 mvi m,0 ; ; write the record to selected record numbe * ;*************************************************** ; ready: ; file is ready for processing ; call readcom ;read next command shld ranrec ;store input record# lxi racters lxi h,buff ;destination rloop1: ;read next character to buff push b ;save counter push h ;next destination call getchr ;character to a pop h ;restore counter ntil cr lxi d,datmsg call print ;data prompt mvi c,127 ;up to 127 characters lxi h,buff ;destination rloop: ;read next character to buff push b ;save counter push h * ;* * ;*************************************************** notq: ; not the quit command, random write? cpi 'W' jnz notw ; ; this is a random write, fill buffer u* ;* * ;*************************************************** notf: ; not a write command, read record? cpi 'R' jnz error ;skip if not ; ; read random record ssages * ;* * ;*************************************************** badver: db 'sorry, you need cp/m version 3$' nospace: db 'no directory space$' datmsg: dbd by de until $ push d call crlf pop d ;new line mvi c,pstring call bdos ;print the string ret ; readcom: ;read the next command line to the conbuf lxi push h ;save next to get cpi ' ' ;graphic? cnc putchr ;skip output if not pop h pop b dcr c ;count=count-1 jnz wloop jmp ready ; ;*** b pop b adc b pop b ;+digit mov c,b mvi b,0 dad b aci 0 mov c,a jnc readc jmp readcom endrd: ; end of read, restore value in a adi '0' ;command cpi 'a' ;translate case? rcter from a to console mvi c,conout mov e,a ;character to send call bdos ;send character ret ; crlf: ;send carriage return line feed mvi a,cr ;carriage return call mvi c,readr lxi d,fcb call bdos ora a ;return code 00? jnz error ; ; read was successful, write to console call crlf ;new line mvi c,128 ;max 128 characte lxi d,conlin;command line readc: ldax d ;next command character inx d ;to next command position ora a ;cannot be end of command rz ; not zero, numeric? sui '0' cpd,prompt call print ;command? mvi c,rstring lxi d,conbuf call bdos ;read command line ; command line is present, scan it mvi c,0 ;start with 00 lxi h,0 ; 0000 ************************************************ ;* * ;* end of read command, all errors end-up here * ;* * ;******************************************* ; lower case, mask lower case bits ani 101$1111b ret ;return with value in chl ; ;*************************************************** ;* * ;* string data area for console meputchr mvi a,lf ;line feed call putchr ret ; parse: ;read and parse filespec lxi d,conbuf mvi c,rstring call bdos lxi d,pfncb mvi c,parsef call bdos ret ; print: ;print the buffer addressers lxi h,buff ;next to get wloop: mov a,m ;next character inx h ;next to get ani 7fh ;mask parity jz ready ;for another command if 00 push b ;save counteri 10 ;carry if numeric jnc endrd ; add-in next digit push psw mov a,c ;value = ahl dad h adc a ;*2 push a ;save value * 2 push h dad h ;*4 adc a dad h ;*8 adc a pop b ;*2 + *8 = *10 dad ;* * ;*************************************************** getchr: ;read next console character to a mvi c,coninp call bdos ret ; putchr: ;write charac******** ; error: lxi d,errmsg call print jmp ready ; ;*************************************************** ;* * ;* utility subroutines for console i/o * 'type data: $' errmsg: db 'error, try again.$' prompt: db 'next command? $' entmsg: db 'enter filename: $' ; ;*************************************************** ;* D 20H ;MAKE En00 DFB $67 ;LD H,A DFB $77 ;LD (HL),A ;HIT ANYWHERE IN Cn00 DS START+768-*,0 ;pad to end of sector 40 * Name : CheckROM * Function: Test for 256 bytes of ROM * Input : SlotPtr * Output : Carry CLR if ROM present * : SET if not * Volatile: none REP 40 * CheckROM EQU * PHA ;save AC TYA ; and Y PHA TXA ; and X PHA * * Checksum e following Z80 code is moved into the "other" card's * Zeropage area so that it returns to us "unhappy"... * * FOR Z-CARD, THIS LOADS AT $9000 FOR UNHAPPY CP/M-CARD: * ZCODE EQU * DFB $00 ;NOP DFB $3A DW Z80SLOT+$7000 ;LD A,(ZPAGE+Z80SLOT) DFB $D6,:>2 CP/M 3 DUMP - Version 3.0$ ERROR: File Not Found $ Enter Password: $ Password Error$ ERROR: No Records Exist$ Press RETURN to continue $,* ;* fixed and variable data area * ;* * ;*************************************************** conbuf: db conlen ;length of console buffer consiz: ds 1 ;resulting size t stable? BNE NotRom ;->nope, no ROM there... DEX BNE CheckROM2 CLC ;OK JMP ChkRomX ;return * NotRom EQU * SEC ;no dice * ChkRomX EQU * PLA ;restore TAX ; X PLA ; and TAY ; Y PLA ; and AC RTS REP 40 * Name : Sum * Function: Add up 256the ROM several times, making sure it comes out * the same all times. If not, then it ain't ROM. * JSR Sum ;compute the sum once STA SumValue ;save it * LDX #20 ;that's enough times... CheckROM2 EQU * JSR Sum ;compute the sum again CMP SumValue ;is iDUMP VERSION 3.0 DUMP.COM COPYRIGHT 1982, DIGITAL RESEARCH151282654321Ҋ ҏ>.Ï_ Ҧ0Ï7Ï͜Ü\2|::Iͺ>2 :2$60 ;SUB 60H ;MAKE 6n00 DFB $67 ;LD H,A DFB $77 ;LD (HL),A ;HIT ANYWHERE IN Cn00 ZCODELEN EQU *-ZCODE * * FOR CP/M CARD, THIS LOADS AT $1000 FOR UNHAPPY Z-CARD: * DFB $00 ;NOP DFB $3A DW Z80SLOT+$F000 ;LD A,(ZPAGE+Z80SLOT) DFB $C6,$20 ;ADInvalid ;assume invalid CPY #$10 ;invalid opcode? BEQ ChkExit ;->yep, the card's unknown LDA #R.Other ;something else again * ChkExit EQU * STA SlotPtrH ;hold the return code PLA ;restore TAY ; Y LDA SlotPtrH ;restore the return code RTS PAGE REPafter read conlin: ds 32 ;length 32 buffer conlen equ $-consiz ; pfncb: dw conlin dw fcb ; ds 32 ;16 level stack stack: end  bytes * Input : SlotPtr * Output : AC=sum * Volatile: Y REP 40 * Sum EQU * LDY #0 TYA Sum2 EQU * CLC ADC (SlotPtr),Y ;add another byte INY BNE Sum2 RTS * DiskId EQU * ;disk id bytes for "Bootable" DFB 0,$20,0,$00,0,$03,0,$3C ;odds only * * Th*!""ͮͷ͇*"͛~ͫ#*}#"%"*̀*}K|K*ͺ-m121=2#\:}mͺ2>o:  /\ͺ 1gn~ͻ͙D.:ܰg+"f>2>û>!6 #=!~a1{1 w##:Ƃ2*6 2fl:<2!G\:>2 *|ͫ}*ͫ>:Ï:> ͏> Ï> Ï:_:<2>2ͺ >Ï*}o|LD A,(ZPAGE+Z80SLOT) DFB $C6,$20 ;ADD 20H ;MAKE En00 DFB $67 ;LD H,A DFB $77 ;LD (HL),A ;HIT ANYWHERE IN Cn00 DS START+768-*,0 ;pad to end of sector 20H ;MAKE En00 DFB $67 ;LD H,A DFB $77 ;LD (HL),A ;HIT ANYWHERE IN Cn00 DSREAD IT * * NOW THAT EVERYTHING'S LOADED, INITIALIZE THINGS: * RUN EQU * JSR INIT JSR SETKBD JSR SETVID JSR HOME LDX SLOT LDA MOTOROFF,X ;TURN OFF DRIVE MOTOR JMP CRANKZ80 * SKP 5 STEP EQU * INC HALFTRK ;BUMP IN 1/2 TRACK LDA HALPER PHASE ON MOTOROFF EQU $C088 ;DRIVE MOTOR OFF PAGE ORG $0800 START EQU * DFB 1 ;HOW BIG WE ARE (SECTORS) * LDA POINTA+1 ;WHERE DID SECTOR LOAD? CMP #<$800+$100 ;AT PAGE 8? BNE READ ;->NO, WE'RE READING * * WE'VE JUST BEEN BOOTED. SETUP STA SECTOR ;SET FOR BOOTPROM * * FIGURE OUT WHAT TRACK WE WANT: * TYA ;TRK/SEC LSR A ;MAKE HALFTRACK LSR A LSR A AND #$FE ;DROP SECTOR BIT STA TRK ;SET FOR BOOTPROM LSR TRK CMP HALFTRK ;ARE WE ALREADY THERE? BEQ SEEKDONE ;->YES * RK DS 1 ;TRACK DESIRED * * GENERAL ZEROPAGE USAGE: * TEMP DS 2 ;FOR JUMP-INDIRECT HALFTRK DS 1 ;FOR SEEKING DEND * * BOOT-PROM ENTRY POINTS: * RETRY EQU $5C ;OFFSET TO READ ROUTINE * * APPLE MONITOR ENTRY POINTS: * WAIT EQU $FCA8 ;DELAY * STA TEMP ;JMP SET FOR CN5C * LDA #0 ;CURRENT TRACK IS STA HALFTRK ; ZERO * * NAIL THE RESET-VECTOR: IF USER PRESSES RESET, WE * GO RIGHT BACK TO THE BOOT PROCESS... * LDA #0 STA $03F2 STA $03F3 STA $03F4 * * READ THE SPECIFIED SECTOPARAMS FOR THE BOOT PROM * SO THAT WE CAN READ IN THE REQUESTED SECTORS: * LDX SLOT ;GET BOOT SLOT LDA PHASEOFF+0,X ;PHASE-A OFF * TXA LSR A ;CONVERT TO CN00 LSR A LSR A LSR A ORA #$C0 ;CONSTRUCT JUMP ADDRESS STA TEMP+1 LDA #RETRY SBTL 'CP/M-CARD AND Z-CARD BOOTSTRAP' IBUFSIZ 30 ********************************************* * * * CP/M-CARD BOOTSTRAP LOADER * * * * RICK AURICCHIO 07/26/83 * *-------------------------------------------* * * DO THE SEEK: * JSR STEP ;STEP THE HEAD JSR STEP ;STEP THE HEAD JSR WAIT ;SETTLING TIME (AC=0) * SEEKDONE EQU * LDA LOADADDR,Y ;GET LOAD ADDRESS BEQ READ ;->00:SKIP THIS ONE STA POINTA+1 ;STUFF BUFFER ADDRESS LDX SLOT JMP (TEMP) ;->GO INIT EQU $FB2F ;INIT SCREEN PARAMS HOME EQU $FC58 ;CLEAR SCREEN COUT EQU $FDED ;PRINT A CHARACTER SETKBD EQU $FE89 ;DO IN#0 SETVID EQU $FE93 ;DO PR#0 * * DISK II CONTROLLER EQUATES: * PHASEOFF EQU $C080 ;STEPPER PHASE OFF PHASEON EQU $C081 ;STEPRS: * READ EQU * INC COUNT LDY COUNT ;GET THE INDEX CPY #ENDSEC+1 ;ARE WE DONE? BCS RUN ;->ALL DONE LOADING * * SET UP THE DESIRED SECTOR FOR THE BOOTPROM: * TYA ;TRK/SEC AND #$0F ;RETAIN LOGICAL SECTOR TAX LDA PHYS,X ;GET PHYSICAL ************************************* * CPMCARD EQU 1 ZCARD48 EQU 0 ZCARD64 EQU 0 * * BOOT-PROM DATA FIELDS: * DSECT ORG $26 POINTA DS 1 ;BUFFER POINTER ORG $2B SLOT DS 1 ;BOOT SLOT ORG $3D SECTOR DS 1 ;LAST PHYS SECTOR READ ORG $41 T * * THIS PROGRAM RESIDES IN TRACK 0, SECTOR 0 * * OF A Z-CARD DISKETTE. IT IS DERIVED * * FROM THE "GENERALIZED 28K BOOTSTRAP" * * PROGRAM. * * * * (C) 1983, ADVANCED LOGIC SYSTEMS, INC. * * * ********FTRK ;GET HALFTRACK AND #3 ;PHASES 0..3 ASL A ;*2 FOR ADDRESSING ORA SLOT TAX STA PHASEON,X ;TURN IT ON LDA #80 JSR WAIT STA PHASEOFF,X ; AND OFF RTS PAGE * * LOCAL DATA: * COUNT DFB -1 ;STARTS AT -1 * * TABLE OF PHYSICAL SECTORSFB <$0D00 ;T0,S08 : DISK ROUTINES DFB <$0E00 ;T0,S09 : DISK ROUTINES DFB <$0F00 ;T0,S10 : DISK ROUTINES DFB <$1100 ;T0,S11 : 6502/Z80 LINKAGE DFB <$1000 ;T0,S12 : ZBOOT DFB 0 ;T0,S13 : SKIP IT DFB 0 ;T0,S14 : SKIP IT DFB 0 ;T0,S15 : SKIP (00) MEANS "SKIP IT". * NOTE: YOU MAY NOT LOAD INTO PAGES: * 00, 01, 02, 03, 08, 09, 0A * LOADADDR EQU * **** TRACK 00 **** DFB 0 ;T0,S00 : SKIP IT DFB <$0900 ;T0,S01 : BOOT PART 2 DFB <$0A00 ;T0,S02 : BOOT PART 3 DO CPMCARD DFB <$8800 00 ;T1,S02 : BIOS DFB <$AD00 ;T1,S03 : BIOS DFB <$AE00 ;T1,S04 : BIOS DFB <$AF00 ;T1,S05 : BIOS FIN ENDSEC EQU *-LOADADDR ;THE MAX COUNT DS START+256-*-3-8,0 ;FILL TO END OF SECTOR IOTABLE EQU * ;SLOT ROM TYPES DFB 0 ;SLOT 0 DFB 0 ;SLOT 1 S09 : CPMLDR DFB <$9E00 ;T1,S10 : CPMLDR DFB <$9F00 ;T1,S11 : CPMLDR DFB <$A000 ;T1,S12 : CPMLDR DFB <$A100 ;T1,S13 : CPMLDR DFB <$A200 ;T1,S14 : CPMLDR DFB <$A300 ;T1,S15 : CPMLDR **** TRACK 02 **** DFB <$A400 ;T2,S00 : CPMLDR DFB WHICH CORRESPOND TO THE * LOGICAL SECTORS 0..F ON THE DISKETTE: * PHYS EQU * ;LOG-->PHYS DFB $00 ;00-->00 DFB $03 ;01-->03 DFB $06 ;02-->06 DFB $09 ;03-->09 DFB $0C ;04-->0C DFB $0F ;05-->0F DFB $02 ;06-->02 DFB $05 ;07-->05 DFB $0 ROUTINES DFB <$1300 ;T0,S04 : DISK ROUTINES DFB <$1400 ;T0,S05 : DISK ROUTINES DFB <$0B00 ;T0,S06 : DISK ROUTINES DFB <$0C00 ;T0,S07 : DISK ROUTINES DFB <$0D00 ;T0,S08 : DISK ROUTINES DFB <$0E00 ;T0,S09 : DISK ROUTINES DFB <$0F00 ;T0,SIT **** TRACK 01 **** DFB <$AA00 ;T1,S00 : BIOS DFB <$AB00 ;T1,S01 : BIOS DFB <$AC00 ;T1,S02 : BIOS DFB <$AD00 ;T1,S03 : BIOS DFB <$AE00 ;T1,S04 : BIOS DFB <$AF00 ;T1,S05 : BIOS FIN DO ZCARD64 ;64K ZCARD SYSTEM DFB <$1200 ;T0,S03 : DISK;T0,S03 : DISK ROUTINES DFB <$8900 ;T0,S04 : DISK ROUTINES DFB <$8A00 ;T0,S05 : DISK ROUTINES DFB <$8B00 ;T0,S06 : DISK ROUTINES DFB <$8C00 ;T0,S07 : DISK ROUTINES DFB <$8D00 ;T0,S08 : DISK ROUTINES DFB <$8E00 ;T0,S09 : DISK ROUTINES DF DFB 0 ;SLOT 2 DFB 0 ;SLOT 3 DFB 0 ;SLOT 4 DFB 0 ;SLOT 5 DFB 0 ;SLOT 6 DFB 0 ;SLOT 7 BOOTSLOT DS 1 ;BOOT SLOT $N0 Z80HAPPY DFB 0 ;<>0 IF Z80 IS HAPPY Z80SLOT DFB $C7 ;PASSED TO THE Z80 CHN CPMBOOT2 SLOT 7 BOOTSLOT DS 1 ;BOOT SLOT $N0 Z8 <$A500 ;T2,S01 : CPMLDR FIN DO ZCARD48 ;48K ZCARD SYSTEM DFB <$1200 ;T0,S03 : DISK ROUTINES DFB <$1300 ;T0,S04 : DISK ROUTINES DFB <$1400 ;T0,S05 : DISK ROUTINES DFB <$0B00 ;T0,S06 : DISK ROUTINES DFB <$0C00 ;T0,S07 : DISK ROUTINES D8 ;08-->08 DFB $0B ;09-->0B DFB $0E ;0A-->0E DFB $01 ;0B-->01 DFB $04 ;0C-->04 DFB $07 ;0D-->07 DFB $0A ;0E-->0A DFB $0D ;0F-->0D PAGE * * THESE TABLES CONTAIN THE MEMORY ADDRESS TO WHICH THE * LOGICAL SECTORS WILL BE LOADED. * A ZERO 10 : DISK ROUTINES DFB <$1100 ;T0,S11 : 6502/Z80 LINKAGE DFB <$1000 ;T0,S12 : ZBOOT DFB 0 ;T0,S13 : SKIP IT DFB 0 ;T0,S14 : SKIP IT DFB 0 ;T0,S15 : SKIP IT **** TRACK 01 **** DFB <$AA00 ;T1,S00 : BIOS DFB <$AB00 ;T1,S01 : BIOS DFB <$AC500 ;T1,S01 : CPMLDR DFB <$9600 ;T1,S02 : CPMLDR DFB <$9700 ;T1,S03 : CPMLDR DFB <$9800 ;T1,S04 : CPMLDR DFB <$9900 ;T1,S05 : CPMLDR DFB <$9A00 ;T1,S06 : CPMLDR DFB <$9B00 ;T1,S07 : CPMLDR DFB <$9C00 ;T1,S08 : CPMLDR DFB <$9D00 ;T1,B <$8F00 ;T0,S10 : DISK ROUTINES DFB <$0B00 ;T0,S11 : 6502/Z80 LINKAGE DFB <$9000 ;T0,S12 : ZBOOT DFB <$9100 ;T0,S13 : CPMLDR DFB <$9200 ;T0,S14 : CPMLDR DFB <$9300 ;T0,S15 : CPMLDR **** TRACK 01 **** DFB <$9400 ;T1,S00 : CPMLDR DFB <$9